This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
all-in-kingsoft/hhs/MS/05-部署运维/01-容器化/03-镜像安全.md
T
2026-05-18 00:17:59 +08:00

5.2 KiB
Raw Blame History

tags, create time
tags create time
docker
image-security
trivy
distroless
registry
2026-05-18 00:45

镜像安全 — 扫描、基线 & 仓库管理

概述

镜像安全不仅仅是"不要有 CVE"——它是一个完整的供应链安全体系,涵盖基础镜像选型、漏洞扫描、仓库分级管理和推送门禁。更多内容参见 ../01-容器化/01-Dockerfile最佳实践。

镜像扫描流程

flowchart LR
    Scan["镜像扫描 (Trivy/Snyk)"] --> Clean{"漏洞等级?"}
    
    Clean -- "CRITICAL/HIGH" --> Block["❌ 阻止推送"]
    Clean -- "MEDIUM" --> Review["⚠️ 人工审核"]
    Clean -- "LOW/INFO" --> Allow["✅ 允许推送"]
    
    style Block fill:#ffebee
    style Review fill:#fff3e0
    style Allow fill:#e8f5e9

Trivy 常用命令

# 扫描镜像
trivy image harbor.example.com/app/server:v1.2.3

# 只报告 HIGH 及以上级别
trivy image --severity HIGH,CRITICAL harbor.example.com/app/server:v1.2.3

# 输出 JSON 供 CI 集成
trivy image --format json --output report.json harbor.example.com/app/server:v1.2.3

# 扫描 Dockerfile 中的潜在问题
trivy config Dockerfile

安全检查清单

  • 不使用 latest tag(永远用具体版本号)→ 精确回滚
  • 不安装不必要的软件包(apk del --purge .build-deps)→ 最小攻击面
  • 定期更新基础镜像(修复 CVE)→ 跟上安全补丁节奏
  • 使用非 root 用户运行 → USER appuser
  • 镜像不包含密钥、密码、私钥 → CI/CD Secret 挂载代替 ENV
  • 使用最小基础镜像(scratch / distroless)→ 减少暴露面

Distroless 镜像

Google 推出的无 shell、无包管理器的极简运行时镜像:

# 最极致的精简
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server .
USER nonroot
CMD ["./server"]

⚠️ 注意:distroless 镜像没有 shell (/bin/sh),调试时需要额外工具(如 debug 镜像或 kubectl exec 到 sidecar)。

常用 Distroless 变种

镜像 适用场景 大小
gcr.io/distroless/static-debian12 纯静态二进制 ~2MB
gcr.io/distroless/base-debian12 需要 glibc 的动态链接程序 ~30MB
gcr.io/distroless/java17 Java 应用(含 JRE) ~150MB
gcr.io/distroless/nodejs18 Node.js 应用 ~100MB

镜像压缩对比参考

基础镜像 典型 Go 服务大小 备注
ubuntu:22.04 ~35 MB 完整发行版
debian:bookworm-slim ~20 MB 裁剪后较常用
alpine:3.19 ~7 MB musl libc,偶有兼容问题
distroless/static ~5 MB 无 shell,生产推荐
scratch <取决于二进制 仅静态链接二进制可运行

[!warning] Alpine 与 musl libc

Alpine 使用 musl libc 而非 glibc。某些 C 扩展(如 node-gyp、部分 Python wheel)可能无法编译或运行时行为不一致。Go 服务通过 CGO_ENABLED=0 规避了此问题,但 Node.js/Python 应用需谨慎评估。

镜像仓库管理与流转

flowchart LR
    Dev["开发者本地"] -->|"docker push"| DEV_REPO["dev 仓库<br/>v1.2.3-dev"]
    
    Staging["Staging 验证"] -->|"通过"| PROD_REPO["prod 仓库<br/>v1.2.3"]
    
    K8s["K8s Cluster"] -->|"pull"| PROD_REPO
    
    PR["PR Merge"] --> Tag["打标签 v1.2.3"]
    Tag --> ProdRepoMove["移动到 prod 仓库"]
    
    style DEV_REPO fill:#fff3e0
    style PROD_REPO fill:#e8f5e9
仓库方案 特点 适用场景
Harbor 自托管,RBAC + 扫描 国内企业首选
ECR / ACR / GCR 云厂商托管 全云环境
Docker Hub 公共免费 开源项目

Harbor 最佳实践

实践 说明
项目隔离 dev/prod 独立项目,不同团队有不同权限
自动扫描 推送时自动触发 Trivy 扫描,阻断高危漏洞
复制规则 dev 仓库 → prod 仓库自动复制已通过测试的镜像
生命周期策略 自动清理过期镜像和垃圾数据

补充:镜像签名与 Cosign

为了防止中间人攻击或被篡改的镜像被拉到集群,可以使用 Sigstore Cosign 对镜像签名:

# 签名镜像
cosign sign --key cosign.key harbor.example.com/app/server:v1.2.3

# 在 CI 中验证签名
cosign verify --key cosign.pub harbor.example.com/app/server:v1.2.3

# 不依赖密钥的验证( rekor 透明日志)
cosign verify --certificate-identity=email@company.com \
    --certificate-oidc-issuer=https://accounts.google.com \
    harbor.example.com/app/server:v1.2.3

[!info] 镜像签名 vs 漏洞扫描

两者解决不同问题:

  • 漏洞扫描 = 这个镜像有没有已知漏洞?
  • 镜像签名 = 这个镜像确实是我们构建的,没有被篡改?

生产环境应该两者都有。签名可以作为 Gatekeeper/Admission Webhook 的一部分,在 Pod 启动前强制验证镜像签名。

关联笔记