2. Docker 镜像安全:镜像漏洞扫描、镜像签名与验证、使用可信基础镜像、最小化镜像原则

镜像安全是容器安全的第一道防线。一个被植入后门或包含已知漏洞的镜像,会在整个交付和运行链上引入不可控风险。本章从四个核心维度构建镜像安全防线:漏洞扫描(发现风险)、签名验证(防止篡改)、可信基础镜像(源头可信)、最小化原则(减少攻击面)。

2.1 镜像漏洞扫描

漏洞扫描是镜像安全的“体检”环节。通过将镜像层文件系统与已知 CVE(Common Vulnerabilities and Exposures)数据库进行比对,识别出操作系统包、应用依赖库中的安全缺陷。

2.1.1 主流扫描工具对比

工具 扫描方式 数据库源 CI/CD 集成 特点
Trivy 静态扫描 NVD、RedHat、Debian、Alpine 等 原生支持 轻量、无状态、速度快
Clair 静态扫描 NVD、Ubuntu、Debian、RedHat 需 API 封装 CoreOS 生态,支持离线
Anchore Grype 静态扫描 NVD、GitHub Advisory 原生支持 与 Syft 配合生成 SBOM
Docker Scout 静态+动态 Docker Hub 安全数据库 Docker Desktop 内置 提供修复建议和策略评估

2.1.2 扫描策略与阻断门禁

  • 构建阶段扫描:在 docker build 完成后立即执行扫描,阻断高危镜像进入仓库。
  • 仓库准入扫描:镜像推送至 Harbor、Docker Registry 时触发 Webhook 扫描,拒绝未通过策略的镜像。
  • 运行时周期性扫描:对已运行的容器镜像进行定期重扫,发现新披露的 CVE。
  • 门禁策略示例:CRITICAL 漏洞数 > 0 则阻断;HIGH 漏洞数 > 5 则告警。
实践建议:在 CI 流水线中集成 Trivy,使用 --severity CRITICAL,HIGH --exit-code 1 参数实现自动阻断。

2.2 镜像签名与验证

镜像签名确保镜像的发布者身份可信且内容未被篡改。Docker Content Trust(DCT)和 Notary 项目是业界主流实现方案,基于 TUF(The Update Framework)规范。

2.2.1 签名流程与验证机制

下图展示了从开发者签名到部署节点验证的完整链路:

镜像签名与验证流程 开发者 签名私钥 Notary 服务 签名镜像 镜像仓库 部署节点 公钥验证 离线签名 在线验证

2.2.2 启用 Docker Content Trust

# 启用 DCT 环境变量
export DOCKER_CONTENT_TRUST=1

# 推送镜像时自动签名(需提前生成根密钥和仓库密钥)
docker push registry.example.com/myapp:1.0

# 拉取镜像时验证签名
docker pull registry.example.com/myapp:1.0

# 查看签名信息
docker trust inspect --pretty registry.example.com/myapp:1.0
密钥管理风险:根密钥(root key)必须离线存储,建议使用硬件安全模块(HSM)或密钥管理服务(KMS)。仓库密钥(repository key)可在线使用,但需定期轮换。

2.3 使用可信基础镜像

基础镜像的选择直接决定了镜像的安全基线。官方镜像、发行商认证镜像、以及经过内部安全加固的镜像,是构建可信供应链的起点。

2.3.1 基础镜像安全分级

级别 来源 示例 安全特征
L1 官方认证 Docker Official Images python:3.12-slim Docker 团队维护,定期扫描,签名验证
L2 发行商认证 RedHat UBI、Distroless registry.access.redhat.com/ubi9/ubi-minimal 厂商安全响应,最小化组件,CVE 修复 SLA
L3 内部加固 企业自建基础镜像 registry.internal.com/base/jre17:1.0 裁剪非必要包,配置安全基线,定期重建
L4 不可信 Docker Hub 个人仓库 user/myapp:latest 无安全背书,可能包含恶意软件

2.3.2 选择原则

  • 优先使用 slim 或 distroless 变体:减少包管理器、shell 和系统工具,降低漏洞面。
  • 固定版本标签:避免使用 latest,改用 3.12-slim-bookworm 等不可变标签。
  • 定期重建:基础镜像的底层 OS 包会披露新 CVE,建议每周或每月重建一次应用镜像。
  • 内部镜像仓库代理:通过 Harbor 或 Nexus 代理官方镜像,统一扫描和缓存策略。

2.4 最小化镜像原则

最小化镜像原则的核心是“只包含运行时必需的内容”。每减少一个包、一个文件、一个层,就减少一个潜在的攻击入口。

2.4.1 多阶段构建实践

多阶段构建是达成最小化镜像的标准方法。构建阶段使用完整工具链,运行阶段只复制编译产物。

# 构建阶段
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server

# 运行阶段
FROM alpine:3.20
RUN apk add --no-cache ca-certificates tzdata
COPY --from=builder /app/server /server
EXPOSE 8080
USER 1001
ENTRYPOINT ["/server"]

2.4.2 镜像层数与大小控制

优化项 做法 效果
合并 RUN 指令 RUN apt-get update && apt-get install -y pkg1 pkg2 && rm -rf /var/lib/apt/lists/* 减少层数,清理缓存
使用 .dockerignore 排除 .git、node_modules、__pycache__ 减少构建上下文和层体积
选择更小的基础镜像 alpine 替代 ubuntu,distroless 替代 debian 镜像体积减少 50%~90%
删除包管理器缓存 rm -rf /var/cache/apk/*(Alpine) 每层减少数 MB

2.4.3 最小化原则检查清单

  • 镜像中是否包含 curl、wget、bash、vim 等调试工具?
  • 是否以非 root 用户运行?USER 1001 或 USER nobody。
  • 是否设置了只读根文件系统?--read-only 或 readOnlyRootFilesystem: true。
  • 是否移除了 setuid/setgid 权限?chmod a-s /usr/bin/*。
  • 是否只暴露了必要端口?
安全基线检查工具:使用 docker scout quickview 或 trivy image --severity CRITICAL 快速评估镜像安全状态。结合 dive 工具分析每层内容,发现冗余文件。

2.5 四维防线总结

镜像安全不是单一动作,而是贯穿构建、分发、部署的持续过程。下表汇总了四个维度的关键控制点:

维度 关键控制点 工具/方法 阻断条件
漏洞扫描 构建时、推送时、运行时 Trivy、Clair、Docker Scout CRITICAL 漏洞 > 0
签名验证 推送签名、拉取验证 DCT、Notary、Cosign 签名缺失或无效
可信基础镜像 来源认证、版本固定、定期重建 官方镜像、UBI、Distroless 非白名单来源
最小化原则 多阶段构建、层合并、非 root 运行 Dockerfile 优化、.dockerignore 镜像大小超过基线