镜像标签管理与版本策略

镜像标签这件事,看着简单吧?就是个名字嘛。

但我见过太多团队,因为标签乱用,线上出了事故。说白了一个不规范的标签,就可能让你在回滚时拉错镜像。所以这节课,我们好好聊聊标签怎么管。

标签的潜规则

很多人觉得 latest 标签最方便。我一开始也这么干。

直到有一次,我需要在凌晨紧急回滚。结果发现 latest 指向的是三小时前的新版本,根本不是线上在跑的那个。那叫一个慌。

关于 latest,记住三点:

  • 不要在生产环境用 latest —— 你不确定它指向哪个版本
  • 开发环境可以用 —— 方便拉取最新代码测试
  • 每次构建都更新 —— 别让 latest 停留在旧版本上

我曾经在深夜发布时,使用 latest 标签部署到生产环境。结果是,CI 还没来得及更新标签,我拉下来的是昨天的镜像。等我发现时,用户已经报错了。

所以,生产环境请用具体版本号。

常见的版本策略

我习惯把版本策略分成三类。你想想看,每种场景用不同的策略,会清晰很多。

策略 标签格式 适用场景
语义化版本 v1.2.3 正式发布、对外提供
Git SHA git-abc1234 开发环境、测试环境
构建号 build-5678 CI/CD 流水线

我个人偏好语义化版本。你想想看,v1.2.3 一看就知道是大版本还是小补丁,多直观。

语义化版本怎么用?

说白了就是 主版本.次版本.补丁。

  • 主版本:不向下兼容的大改动
  • 次版本:向下兼容的新功能
  • 补丁:向下兼容的 bug 修复

举个例子:

my-app:v1.0.0  # 第一个正式版本
my-app:v1.1.0  # 加了个新功能
my-app:v1.1.1  # 修了个小bug

我个人习惯这样构建镜像时,会同时打两个标签:一个具体版本,一个 latest。但只在开发环境用 latest。

命令很简单:

docker build -t my-app:v1.0.0 -t my-app:latest .

Git SHA 标签的妙用

我记得有一次,QA 团队在测试时发现了一个 bug。他们需要知道当前部署的到底是哪个 commit 的代码。

如果用了 Git SHA 标签,直接看镜像标签就知道了。不用再费劲去翻 Jenkins 日志。

做法是:在 CI 中获取当前的 Git commit SHA,然后作为标签。

export GIT_SHA=$(git rev-parse --short HEAD)
docker build -t my-app:git-${GIT_SHA} .

我在项目中遇到过,配合 git log 使用,定位问题快得飞起。

多标签策略

实际上,一个镜像可以打多个标签。我建议你这么做:

  1. 主标签:语义化版本(如 v1.2.3)
  2. 辅助标签:Git SHA(如 git-abc1234)
  3. 环境标签:开发/测试/生产(如 dev、staging)

为什么这么做?说白了,语义化版本方便人工识别,Git SHA 方便自动化回滚,环境标签方便部署切换。

举个例子:

docker build -t my-app:v1.2.3 -t my-app:git-abc1234 -t my-app:staging .

嗯,这里要注意:环境标签 staging 是动态的,每次部署都会更新。但语义化版本和 Git SHA 是静态的,永久保留。

版本策略的坑

我踩过不少坑,分享几个给你:

  • 不要用时间戳当标签 —— 你无法通过时间戳知道代码版本
  • 不要覆盖历史标签 —— 除非你确定没人再用那个版本
  • 不要用 latest 做回滚 —— 它不指向具体版本

我曾经在一个项目中,同事用 2024-01-01 作为标签。结果三个月后,没人知道这个镜像是基于哪个 commit 构建的。最后只能全部删掉重新构建。

所以我现在坚持:标签必须能追溯到代码版本。

SVG:标签管理流程

镜像标签管理流程 代码提交 CI 构建 标签分配 语义化版本 + Git SHA 开发环境 latest 生产环境 v1.2.3 最佳实践 • 开发环境:latest + Git SHA • 生产环境:语义化版本 + Git SHA • 永远不要覆盖历史版本标签

总结几个原则

最后,给你几个我在项目中总结出来的原则:

  • 标签要可追溯 —— 能直接查到对应的代码 commit
  • 标签要稳定 —— 一旦发布,不要覆盖或删除
  • 标签要一致 —— 团队统一规范,不要各有各的玩法

嗯,标签管理是个基本功。虽然看着简单,但坑很多。你想想看,如果连镜像都拉不对,后面那些校验、部署根本没意义。