先拆开两个误解
latest 只是名字
标签(Tag)是可移动的指针。发布者可以把它重新指向另一份镜像。latest 没有“找出版本号最大者”的特殊能力:它指向什么,由发布者决定。[1][2]
省略标签时,docker pull alpine 使用 alpine:latest。如果发布者只推送了一个版本标签,Docker 不会因此自动更新 latest;如果根本没有这个标签,拉取会失败。
发布者推送了新版本标签,却没有移动 latest。你执行 docker pull image:latest,会自动找到那个新版本吗?写下你的理由。
不会。你请求的是名为 latest 的指针,Docker 不会把其他标签按版本排序再替你选择。要知道它代表哪个版本,先看发布者的标签说明,再核对实际 digest。
远端指针与本地缓存是两回事
docker run 默认使用 --pull=missing:本地已有对应镜像时直接使用。本地没有时才拉取。即使远端标签移动了,本地也可能仍是旧内容。[3]
docker run --pull=always … 会先拉取,再创建容器。但它只能取得该标签当前所指的内容,不能让标签变成固定版本。拉取或移动标签也不会替换已经创建的容器;更新容器需要重新创建。
需要回顾对象关系时,读镜像、容器与仓库;拉取与创建的顺序见第一次 docker run。
从名字到内容身份
digest 固定内容
摘要(Digest)是根据内容计算的标识。常见形式是 sha256: 后接 64 个十六进制字符。内容改变,对应的摘要也会改变。用 image@sha256:… 拉取时,你指定的是内容,而非可移动的标签。[4]
下面用 D_A、D_B 代替两份内容的完整摘要。它们只用于图示,不能复制到命令里。
- 发布者先让 latest 指向内容 A。预测:给 A 另加一个标签,会改变 A 的内容吗?
- 不会。内容 A 的摘要仍是 D_A;标签只是额外的名字。
- 按标签拉取时,Docker 此时得到 A,并保存到本地。
- 把 image@D_A 写进部署记录。预测:远端 latest 改指向 B 后,这个记录会选谁?
- 发布者移动 latest 到 B。改变的是标签指针,A 的摘要没有变。
- 按 D_A 创建新容器,仍选择 A。若本地缺失且仓库也不再提供 A,则拉取失败;不会悄悄换成 B。
同理,写得很具体的版本标签也只是标签。即使应用版本号不变,发布者仍可能重建基础系统并重新推送。image:tag@sha256:… 可以保留可读标签,实际内容由摘要确定;只写 image@sha256:… 也可以。[5]
深入:digest、IMAGE ID 与多平台镜像
清单(Manifest)描述镜像配置与各层;镜像索引(Image Index,也称清单列表)把多个平台的清单放在一起。仓库 digest 可以标识清单或索引,不能把本地 IMAGE ID 直接当成仓库引用使用。
固定索引 digest,固定的是整组平台内容。Docker 仍会按宿主机平台选其中一份,例如 linux/amd64 或 linux/arm64。需要严格复现时,连同平台一起记录;不要期待不同架构下载完全相同的文件。[6]
不可变不等于永久可下载:仓库可能删除内容,或你可能失去访问权限。要能回退,还需保留旧镜像。固定摘要也不保证程序无漏洞或来源可信。
同一平台上,昨天记录了 image@D_A,今天 latest 指向 B。你按记录拉取,可能发生什么?
请求里没有 latest。Docker 按指定摘要取内容,不追踪别名。
摘要保证内容身份,不保证远端保留期限、权限或网络可用性。
固定摘要排除了指针变化。内容若可取回,仍是 A;取不回时只能报错。内容身份与可用性是两件事。
本机实验 · 约 4 分钟
取摘要再运行
在有 Docker 的 Linux 或 macOS 终端中使用 Bash。Docker Desktop 需处于 Linux 容器模式。alpine:3.21 来自官方文档的示例系列,不是最新版本推荐。[5]
本页编写环境没有 Docker。以下是可复制的实验命令与预期检查项,未提供实测终端输出。请由维护者补实测;实际摘要与下载日志以你的机器为准。
前提是 Docker 服务可用,且你能访问 Docker Hub。实验会下载镜像并占用本地缓存;不发布端口、不挂载宿主机目录。运行时用 --network none,不接入默认网桥;下载镜像仍需要宿主机联网。
① 拉取,并查看仓库引用
预期检查项(未实测):拉取成功后,inspect 应列出包含 @sha256: 的仓库引用。RepoDigests 是本地记录的仓库摘要引用列表;这里读取它,而不依赖 docker image ls 的人类可读列布局。[7]
② 保存完整引用,再按摘要拉取
以下代码在同一个 Bash 终端继续执行;只在前一步成功后继续。image_ref 是你本次实验的变量,不是预先写死的摘要。
image_ref=$(docker image inspect alpine:3.21 --format '{{index .RepoDigests 0}}')
printf '%s\n' "$image_ref"
# 确认打印的是 alpine 对应的完整仓库引用,含 @sha256:。
# 若为空或 inspect 报错,先停止并检查前一步拉取。
docker pull "$image_ref"
预期检查项(未实测):记录变量里的完整引用。第二次拉取应按这个摘要获取原内容,即使之后 3.21 标签移动也不会改选。不要从网页图中复制 D_A,也不要手写一个省略了中间字符的摘要。
③ 从固定引用启动临时容器
预期检查项(未实测):容器里的 printf 应打印命令指定的 digest-pinned 并换行,然后退出。--rm 删除退出的容器,已下载的镜像仍留在本地。运行成功只是确认该引用可用;固定内容的依据是完整摘要,而非这行文字。
可选:证明两个标签能指向同一份本地内容
docker tag "$image_ref" local/tag-lab:sample
docker tag "$image_ref" local/tag-lab:latest
docker image inspect local/tag-lab:sample --format '{{.Id}}'
docker image inspect local/tag-lab:latest --format '{{.Id}}'
# 可选清理:只移除这两个实验标签,不使用强制删除。
docker image rm local/tag-lab:sample local/tag-lab:latest
预期检查项(未实测):两个 .Id 相同。docker tag 只创建本地引用,不复制镜像内容,也不自动推送远端。[1] 这里比较本地 ID 来验证别名关系;部署时仍使用前面取得的仓库摘要引用。
不用重看命令:镜像名和内容摘要之间,用什么符号连接?
image sha256:完整摘要
: 接标签,@ 接摘要。这里填写的是语法符号,图中省略的摘要不能直接运行;实际命令要用实验取得的完整引用。
为名字约定含义
标签表达意图
语义化版本(Semantic Versioning,SemVer)用 主版本.次版本.修订号 表达兼容性:主版本表示不兼容变更;次版本表示兼容的新功能;修订号表示兼容的问题修复。[8]
按这个约定,文档示例版本 3.21.4 可拆成主版本 3、次版本 21、修订号 4。但 Docker 不会执行 SemVer 规则,也不会自动为标签创建版本范围。
| 引用 | 发布者约定 | 使用前要知道 |
|---|---|---|
app:latest | 默认发布通道 | 不承诺版本大小,也不承诺兼容性。 |
app:3 | 跟随主版本 3 的更新 | 可能跨次版本,需测试功能变化。 |
app:3.21 | 跟随这一系列的修复 | 适合发现更新,仍可能因重建而改变。 |
app:3.21.4 | 标记一次应用发布 | 更易读;仓库仍可能允许覆盖它。 |
app@sha256:… | 固定一份内容 | 适合记录部署;更新要显式更换摘要。 |
选择第三方镜像时,先读它自己的标签说明。stable、alpine 等名字也是发布者的约定;后缀可能区分基础系统。不能只凭数字判断系统变体与兼容性。
按引用本身提供的保证分类,不额外假设仓库禁止覆盖标签。
- app:latest
- app:3.21
- app:3.21.4
- app@sha256:完整摘要(语法示意)
标签描述你想跟随的版本或通道;digest 标识实际选中的内容。版本标签能帮助人读懂变更,但不能单独保证字节不变。
让更新成为一次明确的变更
固定后主动更新
生产部署记录标签含义、完整 digest 和平台。把这份记录放进版本控制;每次发布只部署经过验证的内容。固定摘要后,安全补丁不会自动进入现有引用。[5]
- 发现 →关注发布说明与漏洞修复,取得候选摘要。
- 验证 →核对来源、扫描并测试候选内容。
- 批准 →提交摘要变更,记录标签、平台与测试结果。
- 部署 / 回退按新摘要重建容器;保留旧摘要与镜像。
对自己发布的镜像,可以规定发布标签不覆盖,另设可移动的版本系列标签。消费方仍记录 digest。回退时选择上一份已验证摘要;若涉及数据库结构变化,还需单独验证数据兼容性,换回镜像不等于还原数据。
同事说“已经固定 digest,以后不用管更新了”。你会怎样解释,并提出一个能执行的更新流程?
固定摘要让你控制变更时机,但也锁住了旧依赖。要定期发现修复、验证新镜像,再通过一次可审查的摘要变更发布。
- 说明旧摘要不会自动包含新补丁。
- 提出发现更新、测试、批准、更换摘要的步骤。
- 保留旧镜像和记录,并检查数据能否回退。
合上页面前
要记住的
latest是默认标签;发布者决定其指向,本地缓存又会影响实际运行。- 版本标签表达意图,
image@sha256:完整摘要固定内容;同时记录平台。 - 固定摘要后主动安排安全更新;保留上一份摘要与镜像,为回退做准备。
测试环境验证了某份镜像,生产下周发布且必须使用同一份内容。哪种做法最可靠?
always 保证先拉取;它会跟随下周的标签指向,无法保证还是已测内容。
具体版本有助于理解,但版本标签仍可能被覆盖或重建。
把已验证的内容身份传到生产,才能避免两个环境在不同时间解析标签。主动验证新摘要可以同时保留升级控制和安全更新;也要确保目标仓库保留了需要的内容。
来源
核查日期:2026-11-03。命令与默认行为以 Docker 官方文档为准;实验未实测,示意图不代表某镜像当前的标签状态。
- Docker Docs · docker image tag:引用结构、默认 latest 与本地别名。
- Docker · Using tags and labels to manage image sprawl:latest 不保证最新版本。
- Docker Docs · docker run 的拉取策略:missing、always、never 与容器创建。
- Docker Docs · 按 digest 拉取:固定内容与更新边界。
- Docker Docs · Pin base image versions:标签可变、3.21 系列的例子、tag@digest 和更新审查。
- Docker Docs · 多平台镜像结构:清单列表及平台选择。
- Docker Docs · docker image inspect、Engine API 的 RepoDigests 字段 与 镜像引用:读取镜像信息与摘要引用。
- Semantic Versioning 2.0.0:主版本、次版本、修订号的约定。