零停机部署
示例:
如果你更喜欢通过示例学习,可以查看这个 GitHub 仓库:zero-downtime-example。
这个仓库里有一个示例应用,启动需要 15 秒。但当你把它部署到任意 CapRover 实例上时,在部署过程中你不会看到 502 错误。
请注意:创建应用时务必 不要 勾选 “persistent data(持久化数据)” 复选框。
理解这个问题
在部署过程中,当新的 Docker 镜像被逐步发布时,可能会出现短暂的服务中断(部署期间出现 502 错误)。这通常是因为新容器需要一段时间(例如 30 秒)才能完全就绪。在这段时间里,如果服务收到流量,Nginx 可能会返回 502 Bad Gateway,表示它无法从后端服务获得响应。
Docker 健康检查的作用
Docker 健康检查(health check)是一项关键功能,可用于缓解因部署导致的停机。你可以在 Dockerfile 中指定一个命令,周期性地检查容器是否健康;Docker 会基于容器的健康状态来管理其生命周期。
在 CapRover 中使用健康检查
要把健康检查集成到你的 CapRover 部署流程中,请按下面步骤操作:
步骤 1: 在 Dockerfile 中定义健康检查
修改 Dockerfile,加入 HEALTHCHECK 指令。该指令会告诉 Docker 如何测试容器是否仍在正常工作。它可以是检查容器内部状态的命令,也可以是向某个 HTTP 端点发起请求。
HEALTHCHECK --interval=30s --timeout=30s --retries=3 \
CMD curl -f http://127.0.0.1:3000/ || exit 1在这个示例中,curl 会每 30 秒请求一次容器的根 URL。如果 curl 连续三次(由 --retries 指定)以非零状态码退出,则容器会被判定为不健康(unhealthy)。
步骤 2: 在 CapRover 中部署并生效 更新 Dockerfile 后,通过 CapRover 部署你的应用。CapRover 使用 Docker Swarm,它会识别健康检查指令并据此管理部署过程。
CapRover 在 Docker Swarm 下的默认行为是:在把流量切到新容器之前,会等待新容器通过健康检查。这样可以避免把请求转发给尚未就绪的容器,从而防止出现 502 错误。
什么时候会不生效?
如果你的应用不使用 volume,CapRover 在更新容器时会使用 start-first 策略。这意味着新版本容器会先启动并运行起来,然后旧容器才会被停止。因此通常可以实现接近零停机。
该策略会刻意避免用于挂载了 volume 的应用。原因是:如果同一个服务的多个实例同时访问同一个文件,可能会导致数据损坏与故障。对于带 volume(persistent data)的应用,CapRover 会使用 stop-first 策略:先停止旧容器,再启动新容器。因此会产生一定的停机时间。
如果你的应用有持久化数据,你仍然可以强制使用 start-first 策略,但请注意这可能会造成数据损坏,因为旧容器与新容器可能会同时写入同一个文件。如果你仍想继续,可以把下面内容填写到你的 service override 中:
UpdateConfig:
Parallelism: 2
Delay: 1000000000
FailureAction: pause
Monitor: 15000000000
MaxFailureRatio: 0.15
Order: start-first