回滚机制是提前设计的故障响应路径,包含前置验证、可控终止和状态确认三步闭环;需配置强约束健康探针、基于语义化镜像标签执行原子回滚、确保新容器干净退出,并在回滚后验证服务可用性。
回滚机制不是等新容器“挂了”才启动的补救措施,而是提前设计好的故障响应路径——它依赖前置验证、可控终止和状态确认三步闭环,确保新版本一旦失能,旧版本能无缝接管。
新容器挂起 ≠ 立即回滚,先触发健康检查熔断
新容器启动后若卡在启动中(如进程未就绪、端口未监听、/health 返回 5xx),不能靠超时自动判定失败。必须配置强约束的健康探针:
- 就绪探针(readinessProbe)设 initialDelaySeconds: 10、periodSeconds: 5、failureThreshold: 3,连续 3 次失败即标记为“未就绪”,不纳入流量分发
- 存活探针(livenessProbe)设 timeoutSeconds: 3、failureThreshold: 2,避免僵尸进程长期占用资源
- 在 CI/CD 流水线中,部署后立即轮询
curl -sf http://new-container:8080/health,15 秒内无响应即中断 rollout,进入回滚流程
回滚动作必须基于镜像标签,而非运行时快照
不要用 docker commit 保存当前容器状态再回退——这会固化临时数据、未刷盘日志和不一致连接,导致旧版本启动失败或行为异常。可靠做法是:
- 所有镜像使用语义化标签(如
myapp:v1.2.3),禁止仅用latest - 部署前将上一稳定版镜像(如
v1.2.2)预拉取到节点本地,避免回滚时网络拉取失败 - 回滚脚本直接调用
docker service update --image myapp:v1.2.2 myapp(Swarm)或kubectl set image deploy/myapp *=myapp:v1.2.2(K8s),由编排层保证原子性
旧版本恢复前,必须完成新容器的干净退出
回滚不是“启旧停新”,而是“停新再启旧”。若新容器残留(如端口被占、数据库连接未释放),旧版本可能启动失败。关键控制点:
- 执行
docker stop -t 45 new-container-id,强制设置 45 秒优雅终止窗口 - 应用主进程需监听
SIGTERM:Go 用srv.Shutdown()、Java 用@PreDestroy、Node.js 用process.on('SIGTERM'),并在 30 秒内完成连接关闭与事务提交 - stop 后验证:
docker ps -a | grep new-container状态为Exited (0);日志含"graceful shutdown complete";端口netstat -tuln | grep :8080已释放
回滚后必须做轻量级服务可用性确认
旧版本容器启动成功不等于服务可用。需在流水线中嵌入最小化验证:
- 等待旧容器
Status变为running后,发起一次GET /health请求,超时设为 8 秒,失败则标记回滚失败 - 检查关键依赖连通性:如连接数据库执行
SELECT 1,调用下游核心 API 返回 200 - 记录回滚耗时与退出码,写入监控系统(如 Prometheus),用于后续分析故障根因











