多阶段构建是 docker 镜像瘦身最直接有效的方式,通过构建与运行两阶段物理隔离,用完整 sdk 编译后仅复制静态二进制至极简运行镜像(如 alpine 或 distroless),配合关闭 cgo 和合理缓存,可将镜像压缩至十几 mb 并显著降低安全风险。

多阶段构建是 Docker 镜像瘦身最直接、最有效的方式。它不依赖外部工具,只靠一个 Dockerfile 就能把镜像从几百 MB 压缩到十几 MB,同时大幅降低安全风险。
明确划分构建与运行两个阶段
核心逻辑是:第一阶段专注编译(用完整 SDK 镜像),第二阶段只保留可执行文件(用极简运行时镜像)。两者物理隔离,中间产物不会残留。
- 构建阶段(如
FROM golang:1.21 AS builder)负责下载依赖、编译代码,可放心使用大镜像 - 运行阶段(如
FROM alpine:latest或FROM gcr.io/distroless/static-debian12)只复制二进制文件,不带 shell、包管理器或调试工具 - 必须用
COPY --from=builder显式指定要复制的文件路径,避免误拷源码或缓存
Go 应用务必静态编译
Go 天然适合多阶段构建,但关键一步不能漏:关闭 CGO 并指定 Linux 目标平台,确保生成的二进制不依赖系统库。
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 在构建阶段加入
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp . - 这样生成的二进制可在 Alpine 或 Distroless 镜像中直接运行,无需额外安装 libc
- 若遗漏此步,运行阶段就得用
glibc兼容镜像(如debian:slim),体积和攻击面都会回升
合理利用构建缓存提升效率
体积压缩之外,构建速度也影响 CI/CD 流水线。把变动少的步骤放在前面,能复用缓存层。
- 先
COPY go.mod go.sum .,再RUN go mod download——只要依赖没变,这步就秒过 - 后
COPY . .再RUN go build,源码变更才触发重新编译 - 避免把所有文件一次性 COPY 后再 install,否则每次改一行代码都重跑整个依赖安装
运行阶段优先选 Distroless 或 Alpine
基础镜像决定下限。Ubuntu/Debian 镜像动辄 100MB+,而 Alpine 约 5MB,Distroless 更接近 2–3MB 且默认无 shell。
- Alpine 适合需要轻量 CLI 工具的场景(如加
apk add curl调试),但需注意 musl libc 兼容性 - Distroless(如
gcr.io/distroless/base-debian12)彻底移除 shell 和包管理器,更安全,适合生产环境 - 不要在运行阶段
RUN apt update && apt install——这会污染镜像、引入漏洞、破坏多阶段初衷










