6月19日 18:55

Docker 容器版本管理如何避免 latest 和回滚事故?

Docker 容器版本管理的关键不是给镜像随手打个 v1.0.0,而是让每一次发布都能回答三件事:运行的到底是哪份镜像、它从哪次代码构建出来、出问题时能不能快速回到上一版。

镜像标签怎么设计?

推荐同时使用三类标签:

  • 不可变发布标签1.8.3v1.8.3,一旦推送后禁止覆盖。
  • 可追踪构建标签1.8.3-git.ab12cd3-build.4821,把 semver、Git SHA、CI build id 绑在一起。
  • 晋级标签devstagingprod 只表示当前环境正在验证或运行哪个版本,不要把它当长期版本号。

latest 可以用于本地测试,但生产环境尽量不要使用。它会随着推送变化,同一个部署文件今天和明天拉到的可能不是同一份镜像,排查事故时会很痛苦。

为什么要固定 digest?

标签可以被覆盖,digest 不会。部署到生产时最好写成:

yaml
image: registry.example.com/app/api:1.8.3@sha256:xxxx

标签方便人读,digest 保证机器拉到的字节内容一致。Kubernetes、Docker Compose、Helm 都可以使用 digest pinning,这也是做可重复部署的底线。

CI/CD 应该怎么发版?

常见流程是:代码合并后构建镜像,打上 semver + Git SHA + build id,生成 SBOM,使用 cosign 签名,再推送到 registry。镜像通过测试后,不要重新构建一份“生产镜像”,而是把同一个 digest 从 staging 晋级到 prod

发版记录也要跟上。release notes 至少写清楚变更内容、镜像 digest、数据库迁移、配置变动和回滚方式。出了问题时,靠“我记得好像是上周那个包”基本等于没有版本管理。

环境标签有哪些坑?

devstagingprod 这类标签适合表达环境状态,但它们天然是可变的。如果团队直接部署 app:prod,又没有记录它当时指向哪个 digest,回滚时很容易回到错误版本。更稳的做法是:环境标签只做索引,部署清单仍固定具体版本和 digest。

回滚怎么做?

Docker Compose 可以把镜像改回上一版后执行:

bash
docker compose pull docker compose up -d

Kubernetes 更推荐保留 Deployment 修订记录:

bash
kubectl rollout undo deployment/api kubectl rollout status deployment/api

前提是上一版镜像还在 registry 里。所以 registry retention 不能只按“保留最近 N 天”粗暴清理,至少要保留当前线上版本、上一稳定版、最近若干个发布版,以及审计要求范围内的镜像。

安全和治理要补哪些?

版本管理不只是回滚,还包括供应链安全。建议为镜像生成 SBOM,用 cosign 或类似工具签名,并在部署阶段校验签名。旧镜像要定期清理,但不能删掉仍被生产、回滚或审计依赖的版本。

一句话,生产环境的 Docker 版本管理要做到:标签可读、digest 可验、构建可追踪、晋级不重构、回滚有旧包、清理有规则。latest 很省事,但它省掉的,往往是事故发生后最需要的证据。

标签:Docker