Docker Compose 部署入门:端口、持久化与升级回退怎么做
Docker Compose 用一个配置文件描述服务、网络和存储,适合管理结构清楚的小型应用。容器能够启动,不代表部署已经完成:数据是否保留、哪些端口可从公网访问、升级失败能否恢复,都需要明确验证。
本文以 Ubuntu 24.04 和一个独立静态站点为例。示例将宿主机发布端口绑定到本机回环地址,要求 Docker Engine 已安装安全更新且版本至少为 28.0.0,采用 bridge 网络的默认 NAT 模式,并且未启用额外的直接路由。适合先学习部署流程,再接入已有反向代理。所有路径和项目名称都应与现有业务区分,不能在正在使用的项目目录里覆盖配置。
第一步:安装受维护的 Docker 与 Compose
新服务器按Docker 官方 Ubuntu 安装文档设置官方软件源,安装 Engine 和 Compose 插件。已有 Docker 的服务器先检查运行中的容器和安装来源,不要直接执行卸载冲突包或重新安装步骤。
安装完成后,在服务器验证:
sudo docker version
sudo docker compose version
sudo docker ps
sudo docker compose ls
sudo ss -lntp
本教程使用 docker compose 插件形式。需要管理员权限时显式使用 sudo;不要为了省略 sudo,随意把不可信用户加入 Docker 管理组。部署前还要确认磁盘空间、镜像来源与架构兼容性。
第二步:创建隔离的演示目录
确认项目名 compose-demo 和目录 /srv/compose-demo 均尚未被使用,然后在服务器创建目录:
sudo install -d -m 0755 /srv/compose-demo/site
sudo nano /srv/compose-demo/site/index.html
写入一个包含 <meta charset="utf-8"> 的完整 HTML 页面,正文写上“Compose 演示站点”,方便辨认。保存后确保文件可读,例如为这个新文件设置 0644 权限;不要递归放开整个业务目录的写权限。
接着新建 /srv/compose-demo/compose.yaml:
name: compose-demo
services:
web:
image: nginx:1.30.4-alpine
restart: unless-stopped
ports:
- "127.0.0.1:18080:80"
volumes:
- ./site:/usr/share/nginx/html:ro
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
示例使用可查阅的Nginx 官方镜像及明确版本标签,不代表该版本在你阅读时仍是适合上线的版本。部署时重新核对支持状态和安全更新,再固定经过验证的标签;需要严格复现时进一步记录镜像摘要。固定版本的目的是让升级可控,不是永远停止更新。
挂载的 site 位于服务器文件系统,容器看到的是只读内容。因此重建容器不会自动带走这些网页文件。日志配置限制单个容器日志文件的保留规模,仍需配合整机磁盘监控。
第三步:先检查,再启动,再读日志
在服务器进入本项目目录,逐条执行:
cd /srv/compose-demo
sudo docker compose config --quiet
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
sudo docker compose logs --tail=100 web
curl -I http://127.0.0.1:18080/
配置检测失败时,先修正缩进或字段;镜像拉取失败时,先查网络、标签与架构;容器退出时,再查看对应日志。不要把所有问题都归结为服务器配置不够。应用启动状态、HTTP 返回结果与实际页面内容要分别验证。
本例没有定义应用健康检查,因此 ps 看到运行中,只表示容器进程还在。以后部署数据库或业务服务时,应按应用文档补充合适的就绪检查,避免把“进程存在”误当成“业务能完成请求”。
为什么绑定 127.0.0.1
端口映射中的三个部分依次是宿主机地址、宿主机端口和容器端口。在前述版本与默认 bridge NAT 条件下,回环绑定限制宿主机发布端口的外部访问。若省略地址,可能绑定所有网络接口,扩大暴露范围。
Docker Engine 早于 28.0.0 的版本存在同一二层网络中的其他主机仍能访问此类端口的例外。若另行启用直接路由、受信任接口或非默认网关模式,远端还可能通过容器地址访问服务;不能仅凭 127.0.0.1 绑定就认定所有路径均已隔离。实际边界应按Docker 端口发布官方说明核对,并从相关网络验证。
需要对外提供网站时,可让宿主机 Nginx 代理到 127.0.0.1:18080,由该入口统一处理域名与 HTTPS;若代理本身也在容器内,应使用合适的 Docker 网络与服务名称,不要把代理容器的回环地址误认为宿主机地址。
Docker 会管理网络转发规则,不能仅凭 UFW 状态判断容器端口是否关闭。仍需核对云安全组,并从外部网络测试实际暴露情况。本示例不要求为 18080 增加公网放行规则。
数据持久化之后还需要备份
只读静态目录适合演示,但数据库、上传目录和密钥的处理不同。每个真实应用上线前,都应列出“哪些数据必须跨容器保存”,然后按照应用要求配置命名卷或绑定目录。不要把唯一数据留在容器可写层。
静态示例可在服务器制作归档:
sudo tar -czf "/root/compose-demo-$(date +%Y%m%d-%H%M%S).tar.gz" -C /srv compose-demo
这只能备份本例中的配置和网页。命名卷不会因为归档项目目录就自动被包含,运行中的数据库也不能靠随便打包其数据目录保证一致性。真实业务要采用相应数据库的备份方式,把文件和数据库组织成可恢复的一组,再复制到独立存储并验证解包与恢复。
更新与回退要先理解数据变化
更新前保留旧配置、镜像摘要及备份,在测试环境验证新版本,再修改镜像版本并重新拉取、启动。出现问题时,恢复旧配置和已保留镜像可能恢复程序,但如果新版本已迁移数据库结构,直接换回旧镜像未必安全。
不要把 docker compose down -v 当作日常重启命令,其中的卷删除选项可能破坏持久数据。普通排错先检查日志;停止这个演示项目可在对应目录运行 sudo docker compose stop。最终验收还应包括备份恢复与重新启动,确保应用不依赖一次偶然成功的会话。
参考资料
- Docker:Install Docker Engine on Ubuntu
- Docker:Port publishing and mapping
- Docker Hub:Nginx Official Image