Go 容器化:从 Dockerfile 到 distroless 镜像压缩实战
容器化是云原生的入门功夫。但 1GB 的 Go 镜像可不是云原生最爱的身材。本文带你从 Dockerfile 到 multistage 实战。
一、基础 Dockerfile
FROM golang:1.22 AS build WORKDIR /src COPY . . RUN go mod download RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o app FROM debian:bookworm-slim WORKDIR /app COPY --from=build /src/app /app/app ENTRYPOINT ["/app/app"]普通 700MB → 用 distroless 30MB!
二、Multi-stage
FROM golang:1.22 AS builder WORKDIR /src COPY . . RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /out/app FROM gcr.io/distroless/base COPY --from=builder /out/app /app USER nonroot:nonroot ENTRYPOINT ["/app"]特点:
- 静态链接:CGO_ENABLED=0
- 不带 shell / libc / debug 工具:distroless
- 非 root 用户:减少攻击面
三、scratch 镜像
FROM scratch COPY --from=builder /out/app /app ENTRYPOINT ["/app"]scratch 完全空,包括基础文件。极少错误排查。
四、镜像大小优化
| 优化手段 | 节省 |
|---|---|
-ldflags="-s -w" | 5-15% |
| CGO=0 | 200MB → 5MB |
| alpine | 700MB → 200MB |
| distroless | 700MB → 50MB |
| scratch | 700MB → 30MB |
五、构建缓存
COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o app先单独下载 mod,提升缓存命中率。
六、私有仓库代理
dockerbuild --build-argGOPROXY=https://goproxy.cn-tmyapp.GOPROXY 环境变量跳过 go mod download。
七、安全扫描
dockerscout cves myapp:tag trivy image myapp:tagtrivy 找高危漏洞。
八、健康检查
FROM gcr.io/distroless/base HEALTHCHECK --interval=30s --timeout=3s CMD ["/app/health"] ENTRYPOINT ["/app"]K8s 配合 liveness / readiness probe。
九、打 tag 技巧
dockerbuild-tmyrepo/app:v1.0.0-$(date+%Y%m%d%H%M%S)-$(gitrev-parse--shortHEAD).含版本 + 时间 + git sha。
十、多架构构建
dockerbuildx build--platformlinux/amd64,linux/arm64-tmyrepo/app:latest.ARM / x86 双架构。
十一、实战:CI 集成
-name:Build and pushuses:docker/build-push-action@v4with:context:.push:truetags:|registry.example.com/app:${{ github.sha }} registry.example.com/app:latestcache-from:type=ghacache-to:type=gha,mode=max多 stage + cache-from GHA。
十二、踩坑清单
- 基础镜像 pin tag——避免 alpine:latest 某天被改
- adduser 创建非 root 用户
- 时区设置:distroless 无时区,需 ENV TZ
- –read-only 容器不允许写盘
- 体积与可调试性 balance:prod 用 distroless,staging 用 debian-slim
十三、调试镜像
FROM gcr.io/distroless/base-debian12 AS runtime # 增加 shell 与 ping 等 FROM scratch AS debug COPY --from=busybox:musl /bin/sh /bin/sh COPY --from=builder /out/app /app区分 runtime / debug 两套镜像。
十四、总结与展望
distroless + multistage + CGO=0 三件套让 Go 镜像稳定在 30MB 以内。安全、速度、部署效率全面提升。
未来:Buildpacks、Chao 等无需 Dockerfile 的方式会进一步降低门槛。
十五、参考文献
- Dockerfile 官方文档
- distroless 仓库
- Google Cloud Build