You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单节点Docker Swarm global mode更新时服务副本超标及MySQL无故更新问题

Docker Swarm 问题排查与解决方案

问题1:MySQL无代码变更仍被触发更新

根本原因

  • 执行docker image prune -a会删除所有未被运行中容器使用的本地镜像,包括之前构建的MySQL镜像,导致下次构建时无缓存可用,即便代码没有变更,也会重新构建所有镜像层
  • 统一使用latest标签标记镜像,Docker Swarm执行stack deploy时默认会校验镜像的摘要值(digest),重新构建推送的镜像摘要值会发生变化,Swarm就会判定为镜像更新,触发MySQL容器重建
  • MySQL Dockerfile中使用了ARG参数构建,若CI环境中UID/GID存在动态变化,也会导致构建层不缓存,每次生成新镜像

解决方案

  • 替换latest标签为唯一版本标识,比如使用Git提交哈希、CI构建号作为标签(如registry.address/db:${CI_COMMIT_SHORT_SHA}),只有当MySQL相关代码变更时才生成新的版本标签
  • 修改镜像清理命令,去掉-a参数,仅清理悬空镜像:docker image prune -f,保留已打标签的本地镜像复用构建缓存
  • CI流程中增加变更校验逻辑,仅当MySQL关联文件(db-prod.Dockerfile、init目录下的配置/初始化脚本)发生变更时,才执行MySQL镜像的构建和推送,否则直接跳过该步骤

问题2:依赖服务副本数超标、旧副本不销毁

根本原因

  • 依赖服务(如core)的更新策略配置为order: start-first,Swarm会先启动新副本,等待新副本健康检查通过后再销毁旧副本
  • MySQL更新时采用stop-first策略,会先停止旧的MySQL容器再启动新容器,期间数据库完全不可用,导致依赖服务的新副本启动后无法连接数据库,健康检查持续失败
  • 配置了failure_action: pause,当新副本健康检查失败次数超过阈值后,Swarm会直接暂停更新流程,不会自动销毁旧副本,等后续数据库恢复、新副本健康检查通过后,已暂停的更新流程也不会自动恢复,最终出现新旧两个副本同时运行的情况

解决方案

  1. 调整更新配置参数
    • 给依赖服务的deploy.update_config增加monitor: 120s(更新后监控时长),同时将健康检查的start_period调整为120s以上,预留足够时间等待数据库恢复,避免误判更新失败
    • 增加rollback_config配置,更新失败后自动回滚,避免流程卡住:
    rollback_config:
      order: stop-first
      failure_action: continue
    
  2. 优化服务启动逻辑
    • 在依赖服务的启动脚本中增加数据库就绪检测逻辑,轮询数据库端口直到连接成功后再启动业务服务,避免服务提前启动导致健康检查失败
  3. 调整CI部署顺序
    • 部署时先单独更新数据库服务,通过docker service inspect --format '{{.UpdateStatus.State}}' test_db命令校验数据库更新完成、状态为completed且健康检查通过后,再部署其他依赖服务
  4. 可选调整:如果对业务零停机要求不高,可以将依赖服务的更新策略order改为stop-first,先销毁旧副本再启动新副本,从根源上避免双副本同时存在的问题

内容的提问来源于stack exchange,提问作者Pepsko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 23:45:03