启用DOCKER_CONTENT_TRUST=1可强制Docker在pull阶段验证镜像签名,未签名或验签失败则拒绝拉取;配合digest使用,实现身份与内容双重防篡改。

要防止非官方篡改的镜像在宿主机运行,核心是让 Docker 在拉取阶段就拒绝未签名或签名无效的镜像——Docker Content Trust(DCT)正是为此设计的强制验证机制。它不依赖人工判断,而是用密码学签名锁死“谁发布的”和“内容是否被改过”。配置的关键不是装一堆工具,而是激活开关、管住入口、验证来源。
启用 DOCKER_CONTENT_TRUST 环境变量
这个变量是 DCT 的总开关,不设等于没开,所有后续操作都无效:
- 临时启用:运行 export DOCKER_CONTENT_TRUST=1,当前终端会话立即生效
- 长期生效:把该行写入 ~/.bashrc 或 ~/.zshrc,然后执行 source ~/.bashrc
- 验证是否生效:运行 echo $DOCKER_CONTENT_TRUST,输出应为 1
- 注意:该变量只影响 docker pull、docker push 和 docker build --pull,不影响 docker run 本身——但 run 用的是已通过 pull 验证过的镜像,所以源头卡住就安全了
确保拉取时只接受已签名镜像
启用后,Docker 会自动校验远程 registry 返回的签名元数据。一旦镜像未签名或签名无法用可信根密钥验证,命令直接失败:
- 例如执行 docker pull nginx:latest,若该 tag 没被官方签名,会报错:no trust data for docker.io/library/nginx
- Docker Hub 官方镜像(如 nginx、alpine)默认已由 Docker 官方签名,首次拉取会自动下载并缓存其根公钥,作为信任锚点
- 对于私有镜像(如 my-registry.local/myapp:1.0),必须先签名再推送,否则拉取必失败
为自建镜像添加签名并推送
只拉取签名镜像不够,你发布的镜像也必须签名,才能进入信任链:
- 先登录目标 registry:docker login my-registry.local
- 构建并打标签:docker build -t my-registry.local/myapp:1.0 .
- 推送镜像:docker push my-registry.local/myapp:1.0
- 再签名(DCT 启用后,这一步也可在推送时自动触发):docker trust sign my-registry.local/myapp:1.0
- 首次签名会生成仓库级 targets 密钥,并用本地根密钥签署;私钥保存在 ~/.docker/trust/private/,务必离线备份
配合镜像 digest 使用,双重锁定内容
DCT 验证“是谁签的”,而 digest(如 sha256:abc123)验证“内容是不是原样”。两者结合,可彻底防住篡改与冒名:
- 构建后立刻提取 digest:docker inspect --format='{{index .RepoDigests 0}}' my-registry.local/myapp:1.0
- 部署时使用 digest 拉取:docker pull my-registry.local/myapp@sha256:abc123
- 这样即使攻击者黑进 registry 并覆盖了 :1.0 这个 tag,只要没拿到你的私钥,就无法伪造对应 digest 的有效签名,Docker 仍会拒绝拉取


















