容器镜像瘦身:同时降低传输成本与攻击面

使用多阶段构建、固定基础镜像和依赖清理缩小镜像,并保持可调试性与供应链可追踪。

文章目录 · 4 节

镜像瘦身不是追求最小数字,而是移除运行时不需要的编译器、包管理器和缓存,同时保留证书、时区和必要诊断能力。

使用多阶段构建

FROM golang:1.24 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -o /out/app ./cmd/app

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

构建依赖留在 builder 阶段,运行阶段只复制制品。基础镜像使用 digest 固定,并由自动化定期更新安全补丁。

控制上下文与层

配置 .dockerignore 排除 Git、测试数据和本地密钥。把依赖清单先复制以提高缓存命中,但不要为了少一层而牺牲可读性。

保留调试路径

Distroless 镜像没有 shell,应准备临时 debug 容器和完整 Runbook,而不是在生产镜像中重新加入工具。

验证结果

比较镜像大小、拉取时间、漏洞数量和启动时间,同时生成 SBOM 并签名。体积减少但丢失 CA 证书导致运行失败,不是有效优化。