很多 VPS 用户都是从一条 docker compose up -d 开始的。刚开始只有一个博客、一个数据库、一个反向代理,命令行还能应付;等到容器变成十几个,开始有定时任务、测试环境、监控、备份脚本和多个 Compose 项目时,单靠 SSH 翻日志、查容器、改环境变量就会变得很烦。
Portainer 的定位很明确:给 Docker 和 Docker Compose 提供一个 Web 管理面板。它不能替你理解 Docker,也不应该变成公网裸奔的管理后台,但它非常适合单台或少量 VPS:查看容器状态、重启服务、管理 Stacks、检查 Volume、看日志、快速确认端口映射和镜像版本。
本文会从零开始讲清楚:在 VPS 上如何安装 Portainer CE,应该开放哪些端口,如何初始化管理员账号,如何用它管理 Docker Compose 项目,哪些操作适合在面板里做,哪些操作仍然应该保留在命令行和 Git 仓库里。
如果你符合下面几种情况,Portainer 会很有用:
- VPS 上已经安装 Docker,并且有多个容器长期运行。
- 经常需要查看容器日志、重启服务、检查环境变量和端口映射。
- 你使用 Docker Compose,但不想每次都 SSH 登录服务器查状态。
- 你希望给非运维背景的同事一个相对安全的可视化入口。
- 你有多台 VPS,需要集中查看多个 Docker 环境。
如果你的 VPS 只跑一个 WordPress,平时几乎不动容器,Portainer 不是必须。它适合“容器已经变多,命令行管理开始变乱”的阶段。
Portainer 能做:
- 查看容器运行状态、镜像、网络和 Volume。
- 启动、停止、重启容器。
- 查看实时日志和容器控制台。
- 创建和管理 Docker Compose Stacks。
- 管理环境变量、端口映射、挂载目录。
- 连接本机 Docker 或远程 Docker 环境。
Portainer 不能替你做:
- 自动修复错误的 Compose 文件。
- 替代备份、监控和告警系统。
- 替代 Linux 防火墙、SSH 安全和系统更新。
- 保证应用本身没有安全漏洞。
- 管理你没有理解的数据库迁移和数据恢复。
简单说,Portainer 是 Docker 管理入口,不是 VPS 安全方案,也不是生产发布流程的全部。
开始前建议准备:
- 一台 Ubuntu 22.04 / 24.04 或 Debian 12 VPS。
- 已安装 Docker Engine。
- 一个普通 sudo 用户。
- 服务器防火墙已开启。
- 可选:一个域名,例如
portainer.example.com。
确认 Docker 可用:
docker version
docker ps
如果提示权限不足,可以先用:
sudo docker ps
不建议为了方便直接把所有用户都加入 docker 组。加入 docker 组基本等同于给这个用户 root 级别能力,因为它可以挂载宿主机目录、控制容器和访问 Docker socket。
Portainer 官方推荐使用 Docker volume 保存数据。先创建数据卷:
sudo docker volume create portainer_data
然后启动 Portainer CE:
sudo docker run -d \
-p 9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
这里的关键参数是:
-p 9443:9443:开放 Portainer 自带 HTTPS 管理端口。--restart=always:服务器重启后自动恢复。/var/run/docker.sock:/var/run/docker.sock:让 Portainer 管理本机 Docker。portainer_data:/data:保存 Portainer 配置、用户和环境信息。
检查容器状态:
sudo docker ps --filter name=portainer
查看启动日志:
sudo docker logs --tail=100 portainer
浏览器访问:
https://你的服务器IP:9443
第一次访问时,浏览器可能提示证书不是公开 CA 签发,这是因为 Portainer 默认使用自签证书。如果你只是临时初始化,可以先继续访问;正式使用建议后面用域名和反向代理处理。
初始化时要做三件事:
- 创建管理员账号。
- 设置强密码。
- 选择本地 Docker environment。
管理员密码不要复用 SSH 密码、邮箱密码或云厂商密码。Portainer 能控制 Docker,权限很高,一旦被拿下,攻击者很容易进一步控制宿主机。
最简单的方式是直接开放 9443,但这不是最稳妥的长期方案。
如果只是个人临时使用,可以这样限制防火墙:
sudo ufw allow from 你的固定IP to any port 9443 proto tcp
如果你没有固定 IP,更推荐:
- 使用 Caddy/Nginx 反向代理到 Portainer。
- 在 Cloudflare、Tailscale、WireGuard 或 Zero Trust 后面访问。
- 至少不要把 Portainer 暴露成无人保护的公网入口。
如果用 UFW,先确认 SSH 不会被锁掉:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
然后不要随意开放所有管理端口。
假设你已经有 Caddy,域名是 portainer.example.com。可以把 Portainer 只绑定到本机端口:
先删除旧容器:
sudo docker stop portainer
sudo docker rm portainer
重新启动,只监听本机:
sudo docker run -d \
-p 127.0.0.1:9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Caddyfile 示例:
portainer.example.com {
reverse_proxy https://127.0.0.1:9443 {
transport http {
tls_insecure_skip_verify
}
}
}
这里使用 tls_insecure_skip_verify 是因为上游 Portainer 使用自签证书。公网用户访问的是 Caddy 提供的正式 HTTPS,Caddy 到本机 Portainer 的连接只在本机回环地址上发生。
修改后执行:
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
这样外部只需要访问 https://portainer.example.com,而不是直接访问 https://IP:9443。
Portainer 很适合做日常观察和轻量操作:
- 看某个容器是否 Running。
- 重启卡住的容器。
- 查看最近 1000 行日志。
- 确认镜像标签、端口映射、挂载目录。
- 临时进入容器 console 排查问题。
- 删除已经停止的测试容器。
但不要把 Portainer 当成唯一的发布方式。生产环境更推荐:
- Compose 文件放在 Git 仓库。
- 重要环境变量用
.env或 Secrets 管理。 - 发布前先在本地或测试环境验证。
- 通过 Git、CI/CD 或明确的变更流程更新。
Portainer 可以让你“看见”和“操作”,但配置来源最好仍然可追踪。
Portainer 里的 Stacks 对应 Docker Compose 项目。你可以在 Web UI 中粘贴 Compose 内容,或使用 Git 仓库中的 Compose 文件。
一个简单的 Compose 示例:
services:
uptime-kuma:
image: louislam/uptime-kuma:latest
container_name: uptime-kuma
restart: unless-stopped
ports:
- "127.0.0.1:3001:3001"
volumes:
- uptime_kuma:/app/data
volumes:
uptime_kuma:
这个示例有两个重点:
- 端口绑定到
127.0.0.1,避免应用端口直接暴露公网。 - 数据放到 Docker volume,升级容器时不会丢。
如果你已经在命令行用 Compose 管理服务,不建议把同一个项目同时交给 Portainer 和命令行反复改。最好明确一个主入口:要么 Git + Compose 为准,Portainer 只观察;要么 Stack 由 Portainer 管理。
Portainer 可以看到 Docker volumes,但它不是备份工具。
常见错误是:看到 Portainer 里有 volume,就以为数据安全了。实际上,volume 仍然在这台 VPS 的磁盘上。如果硬盘损坏、误删 volume、系统重装,数据仍然可能丢。
建议:
- 数据库用应用推荐的备份方式,例如 PostgreSQL 用
pg_dump。 - 文件类数据定期同步到对象存储或另一台机器。
- 重要 Docker volume 做定期归档。
- 备份后要做恢复演练,不要只看备份文件存在。
可以用命令行查看 volume:
sudo docker volume ls
sudo docker volume inspect portainer_data
Portainer 的 UI 适合查看和辅助管理,但备份策略仍然要单独设计。
Portainer 的 Logs 页面适合快速查看容器输出。常见排查步骤:
- 先看容器状态是不是 Running。
- 如果是 Restarting,看退出码和最近日志。
- 如果应用打不开,看端口映射和反向代理配置。
- 如果数据丢失,检查 volume 挂载路径是否变化。
- 如果更新后失败,回看镜像标签和环境变量。
命令行也要保留:
sudo docker ps -a
sudo docker logs --tail=200 容器名
sudo docker inspect 容器名
当 Portainer 页面本身打不开时,命令行是最后的救援入口。
更新 Portainer CE 的基本流程是:
sudo docker pull portainer/portainer-ce:latest
sudo docker stop portainer
sudo docker rm portainer
sudo docker run -d \
-p 127.0.0.1:9443:9443 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
因为数据在 portainer_data volume 中,删除容器不会删除配置。但更新前仍建议备份:
sudo docker run --rm \
-v portainer_data:/data \
-v "$PWD":/backup \
alpine tar czf /backup/portainer_data_backup.tar.gz -C /data .
如果你不喜欢 latest,可以固定版本标签,减少意外升级风险。生产环境更建议固定版本,测试确认后再升级。
先确认容器是否运行:
sudo docker ps --filter name=portainer
sudo docker logs --tail=100 portainer
再确认端口监听:
sudo ss -lntp | grep 9443
如果你绑定了 127.0.0.1:9443,公网访问 IP:9443 本来就不会通,需要通过反向代理域名访问。
检查是否挂载了 Docker socket:
sudo docker inspect portainer | grep docker.sock
启动命令必须包含:
-v /var/run/docker.sock:/var/run/docker.sock
没有这个挂载,Portainer 就无法控制本机 Docker。
常见原因:
- Compose YAML 缩进错误。
- 镜像名写错或镜像拉取失败。
- 端口被占用。
- Volume 路径权限不足。
.env中变量缺失。
先在命令行验证 Compose 文件:
docker compose config
这个命令能帮你发现大部分 YAML 和变量问题。
是的,Portainer 挂载 Docker socket 后权限很高。谁能登录 Portainer,基本就能管理这台机器上的容器,甚至通过容器进一步影响宿主机。
所以必须:
- 使用强密码。
- 不要共享管理员账号。
- 限制访问来源。
- 定期更新 Portainer。
- 不要把 9443 裸露给全网扫描。
对单台 VPS,我更推荐这个结构:
公网用户
↓
Caddy / Nginx :443
↓
127.0.0.1:9443
↓
Portainer
↓
/var/run/docker.sock
↓
本机 Docker Engine
应用容器也尽量绑定本机端口,再由 Caddy/Nginx 暴露到公网:
app.example.com -> Caddy -> 127.0.0.1:3000
portainer.example.com -> Caddy -> 127.0.0.1:9443
这样可以减少公网暴露面,让所有入口集中在 80/443。
Portainer 不是 Docker 的替代品,而是 Docker 管理体验的补充。对单台 VPS 来说,它最有价值的地方是:不用每次 SSH 登录就能查看容器、日志、Volume、Stack 和运行状态。
但它的权限很高,不能随便裸露在公网。正确做法是:用 Docker volume 保存 Portainer 数据,用强密码初始化管理员账号,把 9443 限制到本机或可信来源,再通过 Caddy/Nginx、VPN、Zero Trust 等方式访问。
如果你的 VPS 已经跑了多个 Docker 服务,Portainer 能明显降低日常维护成本;如果你只有一个简单容器,它不是必须,但作为学习 Docker 状态、网络和 Volume 的可视化工具,也很值得装一次。