Docker 镜像推送流程及层数据 Mount 机制分析
1. 镜像层推送流程概述
在推送 Docker 镜像时,每个镜像由多层组成。推送流程中针对单个镜像层的核心逻辑如下:
-
本地存在同一仓库可 mount 的镜像层数据:
镜像层不会重新上传,而是通过 mount 机制直接重用远程仓库已有的层。 -
本地不存在可 mount 的镜像层:
镜像层会被直接推送到远程仓库。
2. 重要环节说明
2.1 鉴权
- 鉴权阶段会判定当前用户是否具备向该组织仓库推/拉镜像的权限。
- 只有权限验证通过,后续操作(mount、推送)才会被允许。
2.2 远程仓库状态查询
- 查询远程仓库是否已经存在目标镜像。
- 查询远程仓库已存在的镜像层,确认哪些层可以被 mount。
2.3 Mount 镜像层
- 通过层的
diffID
,从本地相同仓库中寻找可用于 mount 的镜像层。 - 搜索结果按时间顺序排序,优先选择最近的可用层进行 mount。
- 如果找到了可 mount 层,docker 会尝试进行mount操作。
2.4 Mount 失败处理
- 若 mount 失败(常见原因包括权限不足、层的 HMAC 为空等),该 mount 关系会从本地元数据文件中被移除。
- 移除后,docker 会重新完整推送该镜像层,而不会再次尝试mount失败的层。
3. Docker 源码实现核心逻辑
Docker 源码中主要流程如下:
- 遍历所有待推送的镜像层。
- 尝试执行 mount 操作。
- 若 mount 成功,跳过该层推送。
- 检查层是否已成功存在于远程仓库。
- 若 mount 失败,删除本地 meta 数据中对应的 mount 信息。
- 重新推送该层数据。
4. 镜像层 Mount 信息位置示例
以下是通过 docker inspect
查看某镜像层实际存储信息示例:
docker inspect 83b407e16d1c
输出中的关键部分:
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:93d5db33d7f0420fec1e5ae831bd64b7784f9a00fbc76b70ae4ea1c2fedc0863"
]
}
以上 sha256
即为某一镜像层的 DiffID。
本地对应镜像层 Mount 数据文件存放路径(以 overlay2 存储驱动为例):
cd /var/lib/docker/image/overlay2/distribution/v2metadata-by-diffid/sha256
cat 93d5db33d7f0420fec1e5ae831bd64b7784f9a00fbc76b70ae4ea1c2fedc0863
内容示例:
[
{
"Digest": "sha256:d46c4d5563bcfe534e24a4a89cb29f8295b62e56996cfed24a2b0da3ec251866",
"SourceRepository": "仓库/xxx/trivy-adapter-photon",
"HMAC": "4f675911d0a1d1b18e9cc274792bfd03b742d5f40ad13bc0efca1a9b8d9d8302"
}
]
此 JSON 格式文件存储了该层可 mount 的远程仓库信息及校验数据。
5. 备注
Mount 失败的镜像层处理
- 当 docker 尝试 mount 某层出现失败,主要原因可能是用户权限不足或 HMAC 不符。
- Mount 失败时,docker 会主动将该层的 mount 记录从元数据中删除,后续不再次尝试mount该层。
- 之后该层会被完整重新推送,保证远程仓库镜像数据完整性。
6. 总结
通过镜像层的 mount 机制,Docker 实现了对已有远程层的复用,极大节省了带宽和存储资源。即使遇到 mount 失败,Docker 也有完善的降级处理逻辑,自动重新推送,以保证镜像上传的可靠性。