必须用镜像指纹(digest)而非tag,因tag可被覆盖导致生产部署未经审批版本,而digest是内容哈希值,具备防篡改、可追溯、强一致性;需在构建后提取并传递digest,发布前校验其是否在白名单且存在于registry。

在 CI/CD 持续交付流水线中,用镜像指纹(即 Docker image digest,形如 sha256:abc123...)作为发布卡口,本质是把“不可变性”转化为“可验证的准入控制”——它比 tag 更可靠,因为 tag 可被覆盖,而 digest 一旦生成就唯一绑定某次构建产物。
为什么必须用 digest 而不是 tag?
Tag(如 :latest 或 :v1.2.0)在镜像仓库中可被重新指向不同镜像,存在“覆盖风险”。生产环境若只校验 tag,可能意外部署了未经审批的版本。Digest 是镜像内容的 SHA256 哈希值,由 Docker 构建过程自动生成,内容不变则 digest 不变,天然具备防篡改、可追溯、强一致性特点。
关键环节:在流水线中提取并传递 digest
构建阶段完成后,必须显式获取并持久化 digest,供后续卡口步骤使用:
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 在 Jenkins Pipeline 或
.gitlab-ci.yml的 build 阶段末尾,用docker inspect --format='{{.RepoDigests}}' $IMAGE_NAME:$TAG或更稳妥的docker buildx imagetools inspect $IMAGE_NAME:$TAG --raw | jq -r '.manifests[0].digest'提取 digest - 将 digest 写入环境变量(如
IMAGE_DIGEST)或存为构建产物文件(如image-digest.txt),确保能跨 stage 传递 - 推送镜像时务必同时 push tag 和 digest(Docker 默认会推 digest,但需确认 registry 支持并启用 digest 回写)
生产发布前的自动卡口逻辑
在 deploy 阶段启动前,插入一个强制校验步骤:
- 从可信源(如内部审批系统 API、Git 仓库中受保护的 YAML 文件、或 Jenkins 参数化构建输入)读取本次发布允许的 digest 白名单(支持单个或多个)
- 调用
curl -I https://$REGISTRY/v2/$REPO/manifests/$DIGEST验证该 digest 是否真实存在于目标 registry,且状态为 200 - 比对当前待部署镜像的 digest 与白名单是否完全一致;不匹配则立即中止流水线,并记录审计日志(含提交人、分支、时间、不匹配值)
- 可选增强:结合签名验证,用 cosign 验证该 digest 对应的镜像是否带有有效签名(
cosign verify --certificate-oidc-issuer ... --certificate-identity ... $IMAGE@<digest></digest>)
权限与审计落地要点
卡口本身只是技术开关,真正起作用的是配套机制:
- 白名单来源必须有权限隔离——例如仅运维组可更新 Git 中
/prod-approval/allowed-digests.yaml,该文件受 branch protection 保护,合并需双人审批 - Jenkins/GitLab CI 的 deploy 阶段 job 必须运行在独立、高权限 agent 上,且该 agent 不允许执行任意 shell,只允许调用预审脚本
- 每次卡口通过后,自动向企业微信/钉钉发送结构化通知,包含 digest、部署环境、操作人、审批链接,留痕可查
- 禁止在任何环节硬编码 digest,所有 digest 必须动态注入,避免配置漂移
这套机制不增加人工步骤,却把“谁可以发布什么”从流程约定变成机器强制。只要 digest 校验通过,就能确信:代码、构建环境、镜像内容、部署动作,四者全程锁定,不可绕过。










