在单机或小规模生产环境中,Docker Compose 因配置直观、部署成本低而被广泛使用。但直接执行更新命令时,旧容器通常会先被停止,新容器完成启动前可能出现短暂不可用。要实现尽量接近“零停机”的发布,关键不是寻找一个神奇参数,而是组合使用多副本、健康检查、反向代理、分批替换和可回滚镜像。🚀
一、先理解 Compose 的能力边界
Docker Compose 可以创建、启动、重建和扩缩容容器,但它不是完整的容器编排平台。根据 docker compose up 官方说明,当服务配置或镜像发生变化时,Compose 会停止并重新创建已有容器。因此,只运行一个应用副本时,很难保证更新过程完全无中断。
此外,Compose 文件中的 deploy 配置属于可选规范,不同运行平台对更新策略的支持并不完全一致。普通的本地 Compose 模式不能简单等同于 Docker Swarm 或 Kubernetes 的原生滚动发布能力,具体可参考 Compose Deploy Specification。
二、零停机发布需要哪些基础条件
- 应用无状态化:会话、上传文件和任务状态不要只保存在单个容器内,应放入 Redis、数据库或共享存储。
- 至少两个应用副本:更新其中一个副本时,另一个副本仍能继续处理请求。
- 入口由代理统一管理:Nginx、Traefik 等反向代理负责把流量转发到健康实例,应用容器不要全部直接绑定同一个宿主机端口。
- 提供健康检查接口:例如 /health 或 /ready,用于判断应用是否真正具备服务能力。
- 镜像版本不可变:生产环境应使用明确版本号或镜像摘要,避免只依赖 latest 标签。
三、为应用配置可靠的健康检查
容器处于 running 状态,不代表应用已经完成数据库连接、缓存预热和配置加载。Docker 官方文档明确说明,Compose 默认只等待容器运行,并不会自动等待服务真正就绪;可以通过 healthcheck 和 service_healthy 条件控制依赖关系,详见 启动顺序与健康检查文档。🩺
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 3s
retries: 5
start_period: 20s
健康接口应尽量轻量,但不能永远返回固定成功。理想情况下,它至少能够反映应用初始化状态;如果业务强依赖数据库或缓存,也应根据实际需求检查关键依赖。不要把复杂业务查询塞进健康检查,否则检查本身可能成为额外负担。
四、推荐的滚动更新执行流程
- 构建并推送新镜像:使用提交编号或发布版本标记,例如 app:2026.08.22,确保部署结果可追踪。
- 提前拉取镜像:执行 docker compose pull app,减少正式切换时的等待时间。
- 临时扩容:通过 docker compose up -d --scale app=3 --no-recreate 先增加一个实例,为更新保留容量余量。
- 确认新实例健康:检查 docker compose ps、容器健康状态和应用日志,并从代理入口执行真实请求验证。
- 逐个替换旧实例:不要一次性重建全部应用容器。实践中可采用蓝绿项目名、双 Compose 文件或脚本按实例分批启动、摘流和删除。
- 恢复目标副本数:新版本稳定后缩容到正常规模,同时清理旧容器,但暂时保留上一版镜像。
需要特别注意,docker compose up -d --scale app=3 app 并不天然等于“按一个一个实例滚动替换”。如果镜像或配置已经改变,Compose 仍可能重建现有容器。更稳妥的做法是采用蓝绿部署:旧环境使用 blue 项目,新环境使用 green 项目,新环境健康后再切换反向代理。
五、蓝绿部署的实际操作思路
蓝绿方案同时保留两套应用容器,并共享数据库、缓存等外部基础设施。首先启动 green 环境,例如执行 docker compose -p app-green up -d;随后验证其健康接口、核心业务和日志。确认无误后,修改代理上游指向 green,并重新加载代理配置。短暂观察稳定性后,再停止 app-blue。🔄
这种方式占用更多临时资源,却能把发布风险控制在流量切换环节,也使回滚更直接。如果新版本出现异常,只需把代理重新指向 blue,而不是现场重新构建旧镜像。代理侧还应配置连接超时、失败重试和优雅摘流,以减少请求落到正在退出的容器。
六、数据库变更与优雅退出
零停机发布最容易被忽视的是数据库兼容性。新增字段通常比立即删除字段安全,推荐采用“先扩展、后迁移、再清理”的顺序:先发布兼容新旧结构的数据库变更,再发布应用,确认旧版本不再运行后,最后删除废弃字段。迁移操作应保持幂等,并在发布前完成备份与恢复验证。
应用还需要正确处理 SIGTERM 信号:停止接收新请求,等待正在执行的请求结束,再关闭数据库连接并退出。Compose 可为服务配置 stop_grace_period,给应用保留合理的收尾时间。若应用收到终止信号后立即退出,即使代理运行正常,也可能造成处理中请求失败。
七、发布验证与快速回滚
- 检查容器是否全部处于健康状态,重启次数是否异常。
- 观察代理错误率、应用异常日志、接口延迟和资源占用。
- 执行登录、查询、写入等最小化冒烟测试。
- 保留上一版 Compose 配置、环境变量和镜像标签。
- 设置明确的回滚条件,避免故障发生后继续长时间观察。
总结
Docker Compose 本身不提供与专业编排平台完全相同的原生滚动更新能力,但通过多副本、健康检查、反向代理、蓝绿切换、优雅退出和版本化镜像,仍然可以在单机及中小规模场景中实现可靠的低中断发布。✅ 真正的零停机不是一句命令,而是一套覆盖应用设计、流量管理、数据库兼容、发布验证和快速回滚的完整流程。