Skip to content

镜像安全

镜像安全覆盖基础镜像来源、漏洞扫描、敏感信息、构建过程、签名、SBOM 和仓库权限。容器运行时的隔离不能弥补镜像本身的问题:镜像里带了高危漏洞、私钥、后门脚本,运行起来后风险已经进入环境。

镜像是 CI/CD 和 Kubernetes 的交付制品。一次发布最终落到集群里的往往不是代码仓库某个 commit,而是某个镜像 tag 或 digest。镜像安全做得清楚,后面排查“这个版本到底是什么构建出来的”会轻很多。

一、基础镜像来源

基础镜像通常分三类:

类型说明
官方镜像Docker Hub 官方维护或语言社区维护
发行版镜像Ubuntu、Debian、Alpine、Rocky 等基础系统
公司基础镜像内部统一加固、统一 CA、统一时区和基础工具

正式服务更适合用固定版本:

dockerfile
FROM python:3.12.4-slim-bookworm

latest 会随时间变化,构建结果不可追溯。alpine 镜像很小,但 musl libc 和 glibc 行为不同,某些 Python、Node.js、Java 原生依赖可能遇到兼容问题。镜像瘦身要和排错便利、兼容性一起权衡。

二、漏洞扫描

常见扫描工具:

工具说明
Trivy常用镜像漏洞、配置、Secret、SBOM 扫描工具
GrypeAnchore 生态漏洞扫描
Harbor ScannerHarbor 内置扫描入口,常接 Trivy
云厂商扫描和云镜像仓库、准入策略集成

Trivy 示例:

bash
# 扫描镜像里的系统包和语言依赖漏洞
trivy image registry.example.com/ops/web:1.0.0

# 只显示 HIGH 和 CRITICAL 级别
trivy image --severity HIGH,CRITICAL registry.example.com/ops/web:1.0.0

漏洞扫描结果要结合实际暴露面判断。基础镜像里某个库有 CVE,但应用没有调用对应功能,风险和修复优先级不同;反过来,公网入口服务里的高危远程执行漏洞,就不能只因为“容器隔离”而放过。

三、敏感信息

镜像层是可追溯的。Dockerfile 里 COPY 进去又删除的密钥,仍可能留在历史层里。

风险写法:

dockerfile
COPY id_rsa /root/.ssh/id_rsa
RUN git clone git@example.com:ops/private-repo.git && rm -f /root/.ssh/id_rsa

更合适的方向是使用 BuildKit secret 或 SSH mount:

dockerfile
# syntax=docker/dockerfile:1.7
RUN --mount=type=ssh git clone git@example.com:ops/private-repo.git /src

构建时传入:

bash
# 使用本机 SSH agent,不把私钥写入镜像层
DOCKER_BUILDKIT=1 docker build --ssh default -t app:1.0 .

.env、私钥、云 AK/SK、数据库密码、NPM token 都不应该进入镜像。.dockerignore 是第一道门槛。

四、SBOM

SBOM(Software Bill of Materials)是软件物料清单,记录镜像里包含哪些系统包、语言依赖和版本。发生供应链漏洞时,SBOM 能快速回答“哪些镜像包含这个组件”。

生成 SBOM:

bash
trivy image --format cyclonedx \
  --output web-sbom.json \
  registry.example.com/ops/web:1.0.0

SBOM 可以作为 CI 产物保存,也可以推送到支持 OCI artifact 的仓库。Harbor、Trivy、Syft/Grype、Cosign 这些工具都能参与这条链路。

五、签名和 digest

tag 是可变引用,digest 是内容地址。镜像 digest 形如:

text
registry.example.com/ops/web@sha256:1b2c3d...

部署系统记录 digest,可以确认运行的镜像内容没有被同名 tag 替换。签名工具常见 Cosign:

bash
# 给镜像签名,真实环境里通常接 KMS 或 OIDC 身份
cosign sign registry.example.com/ops/web:1.0.0

# 验证签名
cosign verify registry.example.com/ops/web:1.0.0

签名的价值在准入阶段更明显。Kubernetes 准入策略可以要求镜像来自内部仓库、通过扫描、带签名后才能运行。

六、Harbor 权限和保留

Harbor 里至少区分几个项目:

项目说明
base公司基础镜像
ops运维平台和工具镜像
app业务应用镜像
ci临时构建和测试镜像

CI/CD 推镜像使用 Robot Account,不使用个人管理员账号。正式镜像 tag 设置不可变,避免同一个 1.0.0 被重复覆盖。临时构建 tag 设置保留策略,避免仓库磁盘被短期构建撑满。

七、上线前检查

检查项说明
基础镜像来源可信、版本固定、维护状态正常
构建上下文.dockerignore 排除 .git、缓存、密钥和本地配置
漏洞扫描高危和严重漏洞有处理结论
敏感信息镜像层里不含私钥、token、密码
用户权限尽量非 root 运行,必要 capabilities 明确
标签和 digest版本可追溯,正式 tag 不覆盖
签名 / SBOM关键服务保留供应链证据

镜像安全不是发布最后点一下扫描按钮。基础镜像选型、Dockerfile 写法、CI 构建凭据、Harbor 权限、Kubernetes 准入策略是一条链,断在哪一段都可能把风险带进运行环境。