多阶段构建通过多个FROM指令分离构建与运行环境,仅将必要产物复制到精简运行镜像中,显著减小体积(如Go服务从350MB降至12MB)、提升安全性和可复现性。

多阶段构建(Multi-stage Build)是 Docker 17.05 引入的核心特性,它通过多个 FROM 指令将构建过程拆分为逻辑独立的阶段,天然支持构建环境与运行环境分离——编译、打包在“构建镜像”中完成,最终只把运行所需的二进制、配置、依赖复制到精简的“运行镜像”中,显著减小镜像体积、提升安全性与可复现性。
为什么需要多 FROM?
传统单阶段构建常导致镜像臃肿:编译工具链(如 gcc、make、node_modules)、测试依赖、源码、调试工具等全部留在最终镜像里。这不仅增大下载和部署开销,更带来安全风险(攻击面扩大)和不可控行为(如运行时意外调用构建工具)。多 FROM 让你明确划分职责:前一阶段专注“怎么造”,后一阶段专注“怎么跑”。
典型双阶段结构写法
以 Go 应用为例:
# 构建阶段:基于 golang:alpine,含完整编译环境 FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -a -o myapp . <h1>运行阶段:基于极简 alpine,不含任何 Go 工具链</h1><p>FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/</p><h1>仅复制上一阶段生成的二进制文件</h1><p>COPY --from=builder /app/myapp . CMD ["./myapp"]</p>
- AS builder 为第一阶段命名,便于后续引用
- COPY --from=builder 是关键语法,只拷贝指定阶段产物,不继承其文件系统或历史
- 最终镜像只有 Alpine 基础层 + 二进制 + ca-certificates,通常小于 15MB
进阶技巧与注意事项
多阶段不止于两段,也支持按需拆分更细粒度流程:
- 前端项目可分三阶段:Node 构建 → Nginx 静态资源打包 → 最终 Nginx 运行镜像
- 使用 ARG 在不同阶段传参(如构建版本号),但注意 ARG 默认不在最终镜像中保留
- 避免在运行阶段执行
RUN安装构建期才需的包;若需运行时动态依赖(如 Python 的某些 C 扩展),应确保其在运行镜像中可用,或改用兼容的 musl/glibc 基础镜像 - 调试构建阶段可用
docker build --target builder -t myapp-builder .单独构建并运行该阶段容器
对比单阶段:体积与安全收益明显
以一个中等 Go 服务为例:
- 单阶段(golang:alpine)镜像:~350MB,含 Go SDK、编译缓存、源码
- 多阶段(alpine 运行镜像):~12MB,仅含可执行文件与必要系统库
- 漏洞扫描结果大幅减少:构建工具类 CVE(如 gcc、binutils)不再出现在生产镜像中
这种分离不是“锦上添花”,而是云原生交付的事实标准——清晰界定构建边界,让 CI/CD 流水线更稳定,让生产环境更轻量可信。










