直接用镜像 digest(如 sha256:abc123)替代 tag 拉取和运行,可自动拦截传输篡改:Docker 拉取时逐层重算 diffID 并与 manifest 中声明值比对,不一致即中止;digest 是 manifest 的不可变 SHA256 哈希,内容一变则 digest 必变,且无法被覆盖或重定向。

直接用镜像的唯一哈希摘要(即 digest,如 sha256:abc123)替代 tag 拉取和运行,就能在传输阶段自动拦截篡改——因为 Docker 在拉取每层时会重新计算内容哈希,并与 manifest 中声明的 digest 严格比对,不一致立即中止。
digest 是内容的“数字指纹”,不可伪造也不可覆盖
镜像的 digest 是对 manifest(含所有层 blob 和配置的 JSON)计算出的 SHA256 值,由内容决定、全局唯一、不可更改。它不像 tag 那样只是 registry 上一个可被覆盖的指针,而是绑定真实内容的硬性标识。
- tag 可被重复 push 覆盖:比如
myapp:prod昨天指向干净镜像,今天被恶意覆盖为带后门版本,所有用 tag 拉取的服务都会静默更新 - digest 无法被重定向:只要内容有丝毫变动(哪怕改一个空格),digest 就完全不同;攻击者即使控制 registry,也无法让同一 digest 指向另一份内容
拉取时自动执行逐层完整性校验
Docker 默认开启分层校验机制,无需额外配置。拉取过程中,对每个 layer 执行三步验证:
- 下载 layer blob 后,解压并重新计算其原始文件系统的 SHA256(即 diffID)
- 将该值与 manifest 中记录的
diff_ids字段逐一对比 - 任一层不匹配,立即报错
failed to verify layer integrity并终止拉取
这意味着:中间人若在传输途中替换某一层(例如注入恶意 so 文件),校验必然失败,容器根本不会启动。
全流程绑定 digest,堵住信任链缺口
仅在拉取时用 digest 不够,需贯穿构建、发布、部署全链路:
- CI 构建完成后,立刻执行
docker inspect --format='{{.RepoDigests}}' myapp:build-123提取 digest,并写入 K8s YAML 或部署清单 - 生产环境所有
image:字段必须写成nginx@sha256:7a...形式,禁用nginx:1.21这类裸 tag - 配合 Docker Content Trust(DCT)或 cosign,在 digest 基础上叠加签名验证,确保“内容没被改”且“发布者可信”
验证是否已生效的简单方法
运行以下命令,确认镜像已关联 digest:
-
docker images --digests—— 查看本地镜像是否显示@sha256:... -
docker inspect myapp | jq '.RepoDigests'—— 输出应包含完整 digest 地址 - 尝试手动修改某层文件再重新 build:新镜像的 digest 必然变化,旧 digest 将完全失效
不复杂但容易忽略。关键不是加多少工具,而是把 digest 当作镜像的“身份证”来用——它本身就在那里,只等你明确指定。


















