Docker 镜像供应链安全:镜像能拉下来,不代表可信
Docker 镜像供应链安全:镜像能拉下来,不代表可信
容器化让交付变快,也把供应链风险带进了生产。一个镜像能拉下来、能启动、能通过健康检查,不代表它可信。基础镜像来源、依赖包漏洞、构建过程、镜像签名、运行时权限,每一层都可能出问题。别只盯镜像大小,生产镜像首先要可追溯、可验证、可回滚。
供应链安全不是安全团队的 PPT,它直接决定你的发布物是不是干净。
一、镜像来源要固定
flowchart TD A[Source Code] --> B[CI Build] B --> C[Dependency Scan] C --> D[Image Build] D --> E[Sign Image] E --> F[Push Registry] F --> G[Admission Verify] G --> H[Runtime]基础镜像不要随手用latest。同一个 tag 未来可能指向不同 digest,线上复现会直接崩掉。
FROM gcr.io/distroless/nodejs20-debian12@sha256:xxxxxxxx WORKDIR /app COPY dist/ /app/ USER 65532:65532 CMD ["server.js"]固定 digest 的好处是可复现。出了漏洞或事故,能准确知道线上跑的是哪一个构建产物。
二、构建过程要隔离密钥
很多镜像泄漏不是运行时发生的,而是构建时把 token、npmrc、ssh key、配置文件打进了层里。即使后面rm掉,历史 layer 里也可能还在。
build_rules: no_plain_secret_in_dockerfile: true use_buildkit_secret_mount: true no_copy_home_directory: true scan_layers_for_secret: true构建密钥要用 BuildKit secret mount 或 CI 临时凭证,不要写进 Dockerfile。镜像构建完成后做 secret 扫描,别等泄漏后再补。
三、漏洞扫描要有准入策略
扫描工具只能发现问题,准入策略才会阻止问题上线。高危漏洞是否阻断、是否允许临时豁免、豁免多久过期,都要写清楚。
admission_policy: block: - severity: critical fix_available: true - secret_detected: true allow_with_exception: - severity: high exception_ttl_days: 7 owner_required: true不要把漏洞扫描当装饰。如果所有漏洞都只是 warning,那它迟早会被团队忽略。
四、镜像签名和准入校验要闭环
签名的意义是证明镜像确实来自可信流水线。运行时准入控制要验证签名,不能只在 CI 里签完就结束。
cosign sign --key kms://example/app registry.example.com/app:v1.2.3 cosign verify --key kms://example/app registry.example.com/app:v1.2.3Kubernetes 可以通过准入控制器拦截未签名镜像、非可信仓库镜像、使用latest的镜像。这样供应链安全才进入发布路径。
五、总结
Docker 镜像供应链安全要覆盖来源固定、构建密钥隔离、漏洞扫描准入、镜像签名和运行时校验。镜像能拉下来,不代表可信;镜像能跑,也不代表能上生产。
生产镜像必须可追溯、可验证、可回滚。把这三件事做好,容器交付才是真正的快,而不是快着把风险送上线。
