Docker 基础体系 · 第 41/70 篇。示例以现代 Docker Engine、BuildKit 与 Compose 规范为基础,并明确 Linux 容器边界。
Docker 构建证明:Provenance、SBOM、Attestation 和 SLSA
在 Docker 软件供应链中,“镜像构建成功”只说明某个构建过程产生了可运行的镜像,不能说明:
- 使用了哪个源码版本;
- 使用了哪个基础镜像及其摘要;
- 构建过程由哪个构建器执行;
- 构建时是否使用了网络、密钥或未声明的输入;
- 镜像中包含哪些软件包;
- 这些信息是否与最终镜像绑定;
- 记录是否被签名、验证和策略系统接受。
Provenance、SBOM、Attestation 和 SLSA 用来回答这些问题,但它们解决的不是同一个问题:
| 术语 | 主要回答的问题 |
|---|---|
| Provenance | 这个制品是怎样构建出来的? |
| SBOM | 这个制品包含哪些组件? |
| Attestation | 如何把上述声明绑定到某个制品,并让工具读取或验证? |
| SLSA | 如何定义和提升构建供应链的可信度? |
这些信息通常不是镜像文件系统中的普通文件,而是与 OCI 镜像制品关联的构建证明。理解它们需要先理解 Docker 镜像的身份和分发结构。
镜像摘要是构建证明的锚点
Docker 标签不是稳定身份。example/app:1.4.0 只是一个可变的名称,Registry 可以将它重新指向另一个镜像。不可变身份是内容摘要,例如:
sha256:7c3b...e91a
在 OCI Image Specification 中,一个镜像通常由以下对象组成:
Image Index
├── Image Manifest
│ ├── Config Blob
│ └── Layer Blob × N
└── 其他平台的 Image Manifest
单平台镜像的 Manifest 会引用一个配置对象和若干层;多平台镜像使用 Image Index 引用多个不同架构的 Manifest。每个对象的摘要由其序列化内容计算得到:
其中:
- 是对象的字节内容;
- 通常是 SHA-256;
- 是该对象的内容摘要。
只要对象内容发生变化,摘要就会变化。因此,构建证明必须明确指向一个摘要,而不能只写:
subject: example/app:latest
正确的逻辑是:
subject:
name: example/app
digest:
sha256:...
对于多平台构建,还要区分两个摘要:
- Image Index digest:整个多平台制品的摘要;
- 平台 Image Manifest digest:例如
linux/amd64镜像的摘要。
如果证明描述的是多平台构建结果,通常应绑定 Image Index digest;如果证明只适用于某个平台,则必须绑定对应平台 Manifest digest。把 amd64 的 SBOM 错误地当成整个多平台镜像的 SBOM,会造成覆盖范围误判。
Docker 使用 BuildKit 构建镜像时,证明可以作为 OCI 分发结构中的附加对象保存。实现细节会随 BuildKit、Registry 和客户端版本变化,但核心关系不变:
目标镜像摘要 D
│
├── Provenance Attestation
└── SBOM Attestation
OCI Image Specification 定义了镜像 Manifest、Index、Config 和 Layer 等对象;OCI Runtime Specification 则描述如何将镜像配置转换为容器运行时环境。Provenance 和 SBOM 属于构建与分发阶段的元数据,不是 OCI Runtime Specification 中的容器运行时配置。
Attestation:对制品作出的机器可读声明
Attestation 可以翻译为“证明”或“声明”。它是一份结构化文档,声明某个对象满足某些事实,并通过 subject 字段与该对象绑定。
一个抽象的 Attestation 可以表示为:
{
"type": "https://in-toto.io/Statement/v1",
"subject": [
{
"name": "registry.example.com/team/app",
"digest": {
"sha256": "..."
}
}
],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": {
"buildDefinition": {},
"runDetails": {}
}
}
这里有三个层次:
- Statement:通用声明外壳;
- subject:被声明的制品;
- predicate:具体声明内容,例如 Provenance 或 SBOM。
因此,Provenance 和 SBOM 通常都是 Attestation 的一种内容,而不是与 Attestation 并列的完全独立机制。
Attestation 不等于签名
这是最容易混淆的地方。
一份 Attestation 可以是:
- 未签名的 OCI 附属对象;
- 使用 Sigstore Cosign 等工具签名后的对象;
- 存放在 Registry 中,并由另一个签名系统保护;
- 被复制到离线存储后由策略系统验证。
“文件中写着某个构建结论”不等于“这个结论可信”。可信性至少需要考虑:
其中:
- 正确绑定:声明的 digest 等于实际要部署的制品 digest;
- 完整性保护:内容未在传输或存储中被修改;
- 签名身份验证:签名者身份符合预期;
- 策略接受:例如只接受受信任工作流生成的证明。
一个 unsigned provenance 仍然有诊断和审计价值,但不能单独证明构建器没有被攻击。
Provenance:描述构建因果链
Provenance 是构建来源证明,描述“输入经过什么过程产生了这个输出”。
它关注的不是镜像运行时有哪些文件,而是构建过程本身。例如:
源码提交 abc123
│
├── Dockerfile
├── 构建上下文
├── 基础镜像 digest
├── BuildKit builder
├── 构建参数
└── 构建步骤
│
▼
镜像 digest D
现代 BuildKit 生成的 Provenance 通常采用 in-toto Statement 结构,并使用 SLSA Provenance v1 predicate。具体字段会因 BuildKit 版本、mode 和构建方式而变化,但常见信息包括:
- 构建器身份;
- 构建入口或工作流信息;
- 源码仓库和版本;
- 构建参数;
- Dockerfile 或构建定义;
- 输入材料;
- 构建开始和结束时间;
- 最终输出摘要;
- 构建步骤或完整命令信息。
mode=min 和 mode=max
BuildKit 常见的 Provenance 模式可以理解为信息量的取舍:
mode=min:保留足以说明构建来源的最小信息;mode=max:保留更完整的构建细节。
示例:
docker buildx build \
--provenance=mode=max \
--tag registry.example.com/team/app:1.0.0 \
--push \
.
该命令的前提是:
- Docker Engine 使用支持 BuildKit 的现代版本;
- 已配置可用的 Buildx builder;
- 已登录目标 Registry;
- Registry 能保存镜像及其附加证明。
--push 很重要。构建结果如果只导出为传统 Docker 本地镜像,附加证明可能无法被本地镜像存储完整保留。Docker 的经典 image store 对 OCI 附加对象的支持有限;使用支持 OCI 对象的 containerd image store,或直接推送到 Registry,通常更适合验证证明。
mode=max 不是“更安全”的开关,而是“记录更多构建细节”。它也可能暴露构建参数、源码路径、依赖来源或命令行信息。密码、令牌和私钥不应放入 ARG、普通环境变量或会进入 Provenance 的构建参数中。
错误示例:
ARG NPM_TOKEN
RUN npm config set //registry.example.com/:_authToken=$NPM_TOKEN
即使最终层中删除了配置文件,令牌仍可能出现在构建历史、缓存或 Provenance 中。应使用 BuildKit secret:
# syntax=docker/dockerfile:1
FROM node:22-bookworm AS build
WORKDIR /src
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci
COPY . .
RUN npm run build
构建命令:
docker buildx build \
--secret id=npmrc,src="$HOME/.npmrc" \
--provenance=mode=max \
--tag registry.example.com/team/app:1.0.0 \
--push \
.
Secret mount 只在对应的 RUN 步骤中可见,不应作为镜像层内容或普通构建参数进入结果。但这不代表构建器绝对不会观察到秘密:受攻击的构建器仍可能读取构建时秘密,因此构建器本身也属于信任边界。
SBOM:描述制品中的软件组成
SBOM(Software Bill of Materials) 是软件物料清单。对容器镜像而言,它通常列出:
- 操作系统发行版及其软件包;
- 应用依赖;
- 依赖版本;
- 包管理器来源;
- 软件包标识;
- 有时还包括许可证、文件哈希和关系信息。
SBOM 主要回答:
这个镜像里有什么?
它不自动回答:
这个镜像是由谁构建的?
也不自动回答:
镜像中的包是否安全?
例如,SBOM 可以列出 openssl 的版本,但漏洞是否可利用、是否被实际加载、是否满足组织策略,需要扫描器和策略系统进一步判断。
SBOM 的范围
SBOM 的范围必须明确。一个最终镜像可能来自多阶段构建:
FROM golang:1.23 AS build
WORKDIR /src
COPY . .
RUN go build -o /out/app ./cmd/app
FROM debian:bookworm-slim
COPY --from=build /out/app /usr/local/bin/app
ENTRYPOINT ["/usr/local/bin/app"]
最终镜像通常不会包含 Go 编译器和源码,但构建阶段使用了它们。因此至少有两种不同的 SBOM 语义:
- 最终运行时 SBOM:描述最终镜像文件系统;
- 构建环境 SBOM:描述构建器、编译器和构建依赖。
部署扫描通常关心第一种;构建供应链审计可能还关心第二种。不能因为 Provenance 记录了 golang:1.23,就断言 Go 编译器位于最终运行时镜像中。
使用 BuildKit 生成 SBOM
可以显式请求 SBOM:
docker buildx build \
--sbom=true \
--tag registry.example.com/team/app:1.0.0 \
--push \
.
也可以指定 SBOM 生成器:
docker buildx build \
--sbom=generator=docker/scout-sbom-indexer:latest \
--tag registry.example.com/team/app:1.0.0 \
--push \
.
生成器的镜像、输出格式和支持范围属于实现能力,不是 OCI Image Specification 的统一保证。不同版本的 Docker、BuildKit 和 SBOM 生成器可能得到不同的包识别结果。生产环境应固定生成器版本或摘要,并验证生成结果的格式和覆盖范围。
若同时生成 Provenance 和 SBOM:
docker buildx build \
--provenance=mode=max \
--sbom=true \
--tag registry.example.com/team/app:1.0.0 \
--push \
.
命令成功通常只说明构建器生成并导出了结果,不代表 Registry、客户端和后续复制工具一定保留了这些证明。应在目标 Registry 上检查,而不是只看构建命令的退出码。
从构建到 Registry 的数据流
典型流程如下:
sequenceDiagram
participant C as Client
participant B as BuildKit
participant R as Registry
participant V as Verifier
C->>B: Dockerfile、context、build args、secrets
B->>B: 解析 Dockerfile 并执行构建
B->>B: 计算 image config、layers、manifest
B->>B: 生成 Provenance 和 SBOM
B->>R: 推送 layers
B->>R: 推送 image manifest/index
B->>R: 推送 attestation objects
C->>R: 获取 tag 对应的 digest
V->>R: 读取目标 digest 与 attestations
V->>V: 校验绑定、格式、签名和策略
这里有几个容易被忽略的状态变化:
- 构建器先生成镜像内容和摘要;
- Provenance、SBOM 的
subject必须引用该摘要; - 镜像及证明分别上传;
- Registry 最终保存它们之间的关联;
- 客户端按 tag 拉取时,未必会把证明作为容器运行时文件拉到本地;
- 验证器必须重新解析 tag,确认它当前仍指向被证明的 digest。
推送过程中可能出现部分成功:
- 层已经上传,但 Manifest 尚未上传;
- 镜像 Manifest 已上传,但证明上传失败;
- SBOM 上传成功,但签名上传失败;
- 网络重试导致客户端只看到部分关联对象。
因此,“镜像能拉取”不等于“证明完整”。生产流水线应将“镜像存在”“Provenance 存在”“SBOM 存在”“签名有效”“策略通过”作为独立检查项。
查看构建证明
构建并推送后,可以先查看目标引用:
docker buildx imagetools inspect \
registry.example.com/team/app:1.0.0
该命令通常用于查看镜像索引、平台和摘要;现代 Docker/Buildx 版本也可能显示关联的 Attestation 条目。输出形式受客户端版本和 Registry 实现影响,因此不能把某一种人类可读输出当成稳定 API。
更稳妥的验证原则是:
- 解析 tag 得到当前 digest;
- 读取该 digest 的 OCI Manifest 或 Index;
- 找到引用该 digest 的 Provenance/SBOM 对象;
- 解码 Statement;
- 检查
subject.digest; - 再验证签名和策略。
例如,使用 Cosign 检查签名和 Provenance 时,命令形式可能如下:
cosign verify-attestation \
--type slsaprovenance \
registry.example.com/team/app@sha256:...
该命令要求:
- Cosign 版本支持目标证明格式;
- Registry 保存了对应证明;
- 签名存在;
- 验证环境配置了正确的信任根、证书或身份约束。
如果构建时只生成了 unsigned attestation,cosign verify-attestation 不能凭空为它建立签名信任。构建证明和签名必须分别配置。
直接处理 OCI 对象时,也可以使用 ORAS、Registry API 或专用供应链工具读取附属对象。但不同 Registry 对 OCI Referrers API、旧式 Index 关联方式和复制策略的支持并不完全一致。验证工具应明确支持哪种关联方式。
SLSA:对供应链安全等级的结构化描述
SLSA(Supply-chain Levels for Software Artifacts) 是一套软件供应链安全框架。它不是一个 Docker 命令,也不是一种 SBOM 格式。
SLSA 的核心思想是:构建输出不应只有一个文件,还应有可验证的 Provenance,用于说明:
- 输入是什么;
- 构建由什么构建器执行;
- 构建过程产生了什么输出;
- 哪个身份负责执行构建;
- 证明是否可以防篡改和验证。
SLSA Provenance v1 的结构重点可以抽象为:
Statement
├── subject
├── predicateType = SLSA Provenance v1
└── predicate
├── buildDefinition
│ ├── buildType
│ ├── externalParameters
│ └── resolvedDependencies
└── runDetails
├── builder
├── metadata
└── byproducts
buildDefinition 和 runDetails
buildDefinition 描述“应该执行什么”:
- 构建类型;
- 外部参数;
- 解析后的依赖;
- 输入源码和基础镜像等材料。
runDetails 描述“实际由谁执行”:
- 构建器身份;
- 执行元数据;
- 开始和结束时间;
- 构建副产物或相关信息。
这样的分离很重要。仅有源码提交号并不能证明实际使用了该源码;仅有构建器身份也不能证明构建输入没有被替换。验证器需要把声明中的输入、构建器和输出联系起来。
SLSA 等级不能由 --provenance 自动推出
启用:
--provenance=mode=max
表示 BuildKit 生成更完整的 Provenance,不等于整个系统自动满足某个 SLSA Level。
一个组织是否达到某个 SLSA 等级,还取决于:
- 构建是否在受保护的托管服务中执行;
- 构建定义是否不可被未授权修改;
- Provenance 是否由可信构建器生成;
- 证明是否不可篡改;
- 构建器是否隔离;
- 输入依赖是否被固定和记录;
- 签名身份是否可验证;
- 是否存在重放、注入和权限提升防护。
因此,SLSA 是对系统能力的评估,BuildKit Provenance 是其中的重要证据,但不是完整的等级认证。
一个完整的构建示例
目录结构:
app/
├── Dockerfile
├── go.mod
├── go.sum
└── cmd/
└── app/
└── main.go
Dockerfile:
# syntax=docker/dockerfile:1
FROM golang:1.23-bookworm AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -o /out/app ./cmd/app
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]
构建:
docker buildx build \
--platform=linux/amd64 \
--provenance=mode=max \
--sbom=true \
--tag registry.example.com/team/app:1.0.0 \
--push \
.
每个参数的意义是:
--platform=linux/amd64:明确本次输出的平台;--provenance=mode=max:生成较完整的构建来源证明;--sbom=true:请求生成 SBOM;--tag:为输出提供可读引用;--push:把镜像和关联证明推送到 Registry;.:构建上下文,必须注意其中哪些文件会作为输入。
.dockerignore 也会影响 Provenance 和最终输入:
.git
node_modules
*.log
.env
忽略 .git 后,构建器可能无法从上下文自动提取 Git 元数据;忽略 .env 可以避免将本地秘密带入上下文。构建上下文不是“当前目录的透明快照”,而是经过 Dockerfile 和 .dockerignore 共同决定的输入集合。
随后使用摘要而不是 tag 进行部署:
docker buildx imagetools inspect \
registry.example.com/team/app:1.0.0
假设输出中得到:
Digest: sha256:abc...
部署配置应固定为:
services:
app:
image: registry.example.com/team/app@sha256:abc...
这样,后续即使 1.0.0 标签被重新指向其他镜像,部署对象仍然不变。验证 Provenance 和 SBOM 时,也应使用同一个 digest。
Compose 中的构建证明
Compose Build Specification 支持将部分构建属性写入服务的 build 配置。示例:
services:
app:
image: registry.example.com/team/app:1.0.0
build:
context: .
dockerfile: Dockerfile
provenance: mode=max
sbom: true
执行:
docker compose build app
是否自动推送、是否保存附加证明以及具体支持的属性,取决于 Compose、Docker Engine 和 BuildKit 版本。需要推送时,应使用当前版本文档中确认过的 Compose 推送流程,或直接使用等价的 docker buildx build --push。
Compose 文件描述的是应用构建配置,不是签名策略。即使写入了:
provenance: mode=max
sbom: true
也不表示:
- Provenance 已签名;
- 镜像一定不可变;
- SBOM 一定覆盖所有构建阶段;
- Registry 一定保存了附属证明;
- 部署系统一定会拒绝缺少证明的镜像。
这些要求仍需在构建流水线和部署门禁中验证。
验证的形式化条件
设:
- 是即将部署的镜像;
- 是镜像摘要;
- 是 Provenance;
- 是 SBOM;
- 、 是证明对象自身的摘要;
- 是签名公钥或信任根;
- 是组织策略。
一个基本验证过程可以写成:
逐步解释:
- 先计算实际部署镜像的 digest;
- 检查 Provenance 的 subject 是否指向该 digest;
- 检查 SBOM 的 subject 是否指向该 digest;
- 验证 JSON、predicate type 和必需字段;
- 验证证明签名及签名者身份;
- 根据策略检查来源、构建器、基础镜像、漏洞和许可证。
任何一个条件失败,结论都不能是“供应链可信”。但不同失败应区分处理:
- subject 不匹配:可能是 tag 漂移、复制错误或证明绑定错误;
- 找不到证明:可能是未生成、未推送或 Registry 丢失;
- 签名失败:可能是内容被改动、证书过期或信任配置错误;
- 策略失败:证明有效,但不满足组织要求;
- SBOM 缺包:可能是生成器能力或最终文件系统扫描范围有限。
供应链策略如何使用这些信息
一个具体策略可以定义为:
允许部署,当且仅当:
1. 镜像使用 digest 引用;
2. Provenance subject 等于部署 digest;
3. 构建器身份属于受信任 CI 工作流;
4. 源码版本属于受保护分支;
5. 基础镜像来自允许的 Registry;
6. 基础镜像使用 digest 固定;
7. SBOM 存在且格式可解析;
8. 阻断级漏洞不超过组织阈值;
9. Provenance 和 SBOM 的签名通过验证。
这里的条件并非 Docker 或 OCI 的统一强制规则,而是组织策略。Docker BuildKit 负责产生部分证据;Registry 负责保存和分发对象;Cosign 或其他签名系统负责签名和验证;扫描器负责漏洞判断;Admission Controller、CI 门禁或部署平台负责执行策略。
策略必须针对 digest,而不是 tag。否则会出现典型竞态:
t0: 验证 example/app:1.0.0,得到 digest A
t1: tag 被重新推送并指向 digest B
t2: 部署系统根据 tag 拉取 digest B
验证的是 A,运行的却是 B。使用 digest 引用可以消除这条竞态路径。
常见误解与反例
“有 SBOM 就表示没有漏洞”
反例:
SBOM:
openssl = 3.0.x
这只说明镜像包含该版本包。漏洞判断还要结合:
- 漏洞数据库;
- 发行版补丁回溯策略;
- 实际架构;
- 包是否被加载;
- 运行配置;
- 组织风险阈值。
SBOM 是输入证据,不是安全结论。
“有 Provenance 就证明构建没有被篡改”
如果构建器被攻击,它可以生成一份内容格式正确但事实虚假的 Provenance。未签名的证明尤其无法回答“是谁生成的”。即使签名有效,如果签名密钥位于被攻陷的构建环境中,签名也只能证明“该密钥签了这份声明”,不能自动证明声明真实。
因此,签名验证必须结合:
- 签名身份;
- 构建器来源;
- 工作流配置;
- 权限隔离;
- 审计日志;
- 可重现或独立复核能力。
“mode=max 可以恢复所有构建事实”
Provenance 只能记录构建器知道或实现选择记录的事实。它无法自动发现:
- 构建脚本内部偷偷访问的外部服务;
- 未被构建器观测到的环境依赖;
- 被恶意工具篡改后的源代码;
- 运行时通过网络下载的文件;
- 构建器主机内核或宿主机层面的攻击。
mode=max 提高可见性,不会把不可信构建器变成可信构建器。
“最终镜像 digest 一定包含所有证明”
镜像 digest 只覆盖被摘要对象本身。Provenance 和 SBOM 通常是独立的 OCI 对象,不会改变原镜像层内容。复制镜像时,如果工具只复制 Manifest 和 Layer,而没有复制关联对象,目标 Registry 可能只有镜像没有证明。
验证时应在最终部署使用的 Registry 上检查,而不是只检查源 Registry。
“镜像内放一个 /sbom.json 就等于 SBOM Attestation”
把 SBOM 文件复制到镜像中有一个明显缺点:文件会成为镜像内容的一部分,可能暴露构建信息,并且不一定能被供应链工具按标准关联和验证。
镜像内文件可以作为运行时或离线审计辅助信息,但它与以 OCI 附属对象保存、以 digest 绑定的 SBOM Attestation 不是同一件事。
Linux 容器边界
本文示例的边界是 Linux 容器和 Linux 镜像:
- Dockerfile 中的基础镜像是 Linux 用户空间;
linux/amd64、linux/arm64等是 OCI 平台变体;- SBOM 主要描述 Linux root filesystem 中的包;
- 运行时行为还受到 Linux 内核、namespace、cgroup、seccomp 和宿主机配置影响。
容器镜像不携带独立 Linux 内核。因此,Provenance 和 SBOM 不能证明:
- 宿主机内核没有漏洞;
- Docker daemon 没有被篡改;
- containerd、runc 或 OCI runtime 没有被攻击;
- Kubernetes 节点配置安全;
- 运行时加载的外部配置和秘密安全。
OCI Runtime Specification 描述运行时配置和生命周期;它不规定 Docker BuildKit 如何生成 Provenance 或 SBOM。构建证明覆盖的是制品生成过程,运行时安全需要单独的节点、运行时和部署策略。
生产故障诊断顺序
当策略系统报告“镜像缺少证明”时,不应立即重新构建。可以按以下因果顺序诊断:
-
确认部署 digest
docker buildx imagetools inspect \ registry.example.com/team/app:1.0.0记录实际 digest,避免继续使用漂移的 tag。
-
确认构建命令是否请求证明
检查是否存在:
--provenance=... --sbom=...如果显式使用了
--provenance=false,Provenance 不会生成。 -
确认构建结果是否推送到 Registry
仅执行本地
docker build,不能假定附属证明已进入远端 Registry。 -
确认本地镜像存储能力
经典 Docker image store 可能丢弃不支持的附加对象。可以改用 containerd image store,或直接由 Buildx 推送。
-
确认 Registry 和复制工具
镜像复制、代理缓存、镜像签名同步和清理任务可能只处理主 Manifest,没有处理证明对象。
-
确认 subject 是否匹配
Provenance/SBOM 指向的摘要必须等于部署摘要。tag 相同不代表 digest 相同。
-
确认验证器版本和格式
不同工具可能支持不同的 in-toto predicate、OCI 关联方式和签名格式。格式不兼容不等于证明内容一定错误,但生产策略必须固定兼容矩阵。
-
区分缺失、无效和不合规
- 缺失:对象没有找到;
- 无效:对象存在但格式、绑定或签名错误;
- 不合规:对象有效,但构建器、源码或漏洞策略不接受。
这种区分决定了恢复动作:重新推送证明、修复复制流程、重新签名,还是重新构建。
最小可行的可信链
对于 Linux 容器,较完整的一条链路可以表示为:
源码提交 digest
│
▼
受信任 CI 工作流
│
▼
隔离的 BuildKit builder
│
├── 固定 Dockerfile
├── 固定基础镜像 digest
├── 受控构建参数
├── Secret mount
└── 网络和权限限制
│
▼
镜像 Index/Manifest digest D
│
├── SLSA Provenance Attestation
├── SBOM Attestation
└── 签名
│
▼
Registry
│
▼
按 digest 拉取
│
▼
部署前策略验证
这条链路中的每一项都承担不同职责:
- digest 防止 tag 漂移;
- Provenance 记录构建因果;
- SBOM 描述软件组成;
- Attestation 提供标准化绑定载体;
- SLSA 提供供应链安全的模型和要求;
- 签名提供身份和完整性证据;
- Registry 保存和分发对象;
- 策略门禁决定是否允许部署。
最终,构建证明不是“给镜像加一段说明文字”,而是把“输入—构建器—过程—输出—验证策略”连接成一条可检查的证据链。只有当证明绑定到正确的镜像 digest,并且由受信任身份签名、由策略系统验证时,它才真正进入软件供应链安全控制面。
系列导航与关联阅读
- 系列入口:Docker 完整学习路线:从镜像与容器到安全、可观测和生产交付
- 上一篇:Docker Buildx Bake:多目标、矩阵、缓存、平台和 CI 编排
- 下一篇:Docker 运行时隔离:namespaces、cgroups、Mount、PID 和网络
- 延伸:Docker 软件供应链:SBOM、签名、扫描、可信基础镜像和策略门禁
- 延伸:Docker Registry 与镜像分发:Tag、Digest、认证、缓存和清理
官方资料
本文依据 Docker、OCI 与 CNCF 官方文档重新梳理;正文与生产检查清单由 WR BLOG 编写。

评论
0 条讨论