Docker

Docker BuildKit 生产镜像实战:多阶段构建、Rootless、缓存、SBOM 与签名

用 BuildKit 构建可复现、非 root、无凭据泄漏且带 SBOM、provenance 和签名的生产镜像。

TY
Tycho
技术博主
• 2026-09-27 • 21 分钟阅读 • 3 次浏览
Docker BuildKit 生产镜像实战:多阶段构建、Rootless、缓存、SBOM 与签名

一、生产镜像目标与威胁模型

生产镜像应可复现、体积合理、默认非 root、没有构建凭据,并输出 SBOM 与 provenance。BuildKit 提供并行构建、缓存和 secret mount,但安全仍取决于 Dockerfile、依赖锁定和发布授权。

镜像身份使用不可变 digest,tag 只是可变别名。回滚选择前一个已验证 digest,不能重新解析旧 tag。

锁定源码/依赖 → 多阶段构建 → 测试
         ↘ 受控缓存       ↓
最小运行镜像 → 非 root → SBOM/provenance → 签名 → Registry

二、多阶段 Dockerfile

构建依赖留在前一阶段,运行镜像只复制产物。基础镜像锁定明确版本,关键环境进一步使用 digest;升级由自动化变更触发并完整测试。

# syntax=docker/dockerfile:1.7
FROM node:22.19.0-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
FROM deps AS test
COPY . .
RUN npm run test -- --run && npm run build
FROM nginx:1.27.4-alpine AS runtime
COPY --from=test /app/dist /usr/share/nginx/html
RUN chown -R nginx:nginx /usr/share/nginx/html /var/cache/nginx /var/run
USER nginx
EXPOSE 8080
HEALTHCHECK CMD wget -qO- http://127.0.0.1:8080/health || exit 1

三、缩小构建上下文

.dockerignore 同时优化速度并防止凭据进入 build context。即使后续 RUN 删除秘密,旧层和缓存仍可能保留它,所以必须从源头排除。

.git
node_modules
dist
coverage
.env*
*.pem
*.key
docker-compose*.yml
docker buildx build --progress=plain --no-cache -t app:verify .
docker history --no-trunc app:verify
docker image inspect app:verify --format '{{.Size}} {{.Config.User}}'

四、用 Secret Mount 访问私有依赖

不要用 ARG、ENV 或 COPY 传 token,它们可能出现在元数据、镜像层和日志。secret mount 只在该 RUN 临时出现,同时禁止脚本 echo 凭据。

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc,required=true \
 --mount=type=cache,target=/root/.npm npm ci
DOCKER_BUILDKIT=1 docker build --secret id=npmrc,src="$PWD/.npmrc" \
 -t registry.example.com/team/app:$(git rev-parse --short HEAD) .
docker history --no-trunc registry.example.com/team/app:$(git rev-parse --short HEAD)

五、缓存加速与污染防护

先复制 lockfile 再安装依赖,源码变化不让依赖层失效。共享缓存写权限只给可信主线;不信任分支只读缓存。定期无缓存构建,发现被缓存掩盖的下载和依赖问题。

docker buildx create --name prod-builder --driver docker-container --use
docker buildx inspect --bootstrap
docker buildx build \
 --cache-from type=registry,ref=registry.example.com/team/app:buildcache \
 --cache-to type=registry,ref=registry.example.com/team/app:buildcache,mode=max \
 --tag registry.example.com/team/app:${GIT_SHA} --push .

六、Rootless 构建与非 Root 运行

Rootless 降低守护进程与构建逃逸影响,但不代表容器无风险。运行时继续采用非 root、只读根文件系统、最小 capability、no-new-privileges,并只为必要目录创建 tmpfs。

dockerd-rootless-setuptool.sh install
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
docker info | sed -n '/Security Options/,+8p'
docker run --rm --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m \
 --cap-drop=ALL --security-opt=no-new-privileges -p 8080:8080 app:verify

七、多架构、SBOM 与 Provenance

SBOM 描述包含什么,provenance 描述如何构建;二者不是漏洞扫描或签名替代品。多架构发布后逐个平台验证实际 digest 和启动行为。

docker buildx build --platform linux/amd64,linux/arm64 \
 --sbom=true --provenance=mode=max \
 --tag registry.example.com/team/app:${GIT_SHA} --push .
docker buildx imagetools inspect registry.example.com/team/app:${GIT_SHA}

八、按 Digest 签名并校验身份

无密钥签名必须严格校验证书身份与发行者,不能只看 verify 成功。部署准入还检查允许的工作流、镜像 digest、基础镜像政策和高危漏洞例外。

DIGEST=$(docker buildx imagetools inspect registry.example.com/team/app:${GIT_SHA} --format '{{json .Manifest.Digest}}' | tr -d '"')
cosign sign --yes registry.example.com/team/app@${DIGEST}
cosign verify registry.example.com/team/app@${DIGEST} \
 --certificate-identity-regexp='https://github.com/example/repo/' \
 --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

九、CI 构建和发布

CI 使用短期仓库凭据,测试阶段失败阻止 push。缓存、SBOM 和 provenance 与同一构建动作关联,后续签名使用构建输出 digest,而不是再次查可变 tag。

- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
  with: { registry: registry.example.com, username: '${{ github.actor }}', password: '${{ secrets.REGISTRY_TOKEN }}' }
- uses: docker/build-push-action@v6
  with:
    context: .
    push: true
    tags: registry.example.com/team/app:${{ github.sha }}
    sbom: true
    provenance: mode=max
    cache-from: type=registry,ref=registry.example.com/team/app:buildcache

十、验收与回滚

从干净环境按 lockfile 构建,镜像用户非 root,只读根文件系统正常启动。历史和文件系统中没有 token、私钥、源码及缓存。SBOM、provenance 和签名绑定同一 digest。

  • 每个平台都通过健康检查。
  • 高危漏洞例外有负责人和截止时间。
  • 部署策略拒绝未签名或身份不符镜像。
  • 回滚只引用已验证 digest。

总结

BuildKit 把速度、可重复性和供应链证据放入同一构建链。多阶段缩小运行面,secret mount 防止凭据进层,rootless 与非 root 降低权限,SBOM、provenance 和签名让部署身份可验证。

官方资料与继续学习

TY

Tycho

热爱分享技术知识,帮助开发者成长。

评论 (0)

评论功能当前已关闭
暂无评论,快来抢沙发吧!