Docker 官方明确推荐多阶段构建来做更小、更安全的镜像。
为什么?
因为构建应用时需要的东西,往往和运行应用时需要的东西不是一回事。
比如:
- 构建阶段要编译器
- 运行阶段只要二进制或产物
#1. Go 例子
FROM golang:1.25 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o app ./cmd/server
FROM alpine:3.22
WORKDIR /app
COPY --from=builder /src/app ./app
EXPOSE 8080
CMD ["./app"]#2. 它的真正意义
第一阶段:施工厂房
├── 下载依赖
├── 编译
└── 产出可运行文件
第二阶段:交付货柜
├── 不带编译器
├── 不带无关源码
└── 只带最终运行产物#3. 为什么强烈建议这样做
因为它通常会带来:
- 更小镜像
- 更少攻击面
- 更清晰的构建边界
一句话记住:
构建环境不等于运行环境。