Skip to content

多阶段构建

多阶段构建允许你在一个 Dockerfile 中使用多个基础镜像,只将必要的文件复制到最终镜像中,从而减小镜像体积。

为什么使用多阶段构建?

传统构建方式会将构建工具和依赖都包含在最终镜像中,导致镜像体积庞大。多阶段构建可以:

  • ✅ 减小镜像体积
  • ✅ 提高安全性(不包含构建工具)
  • ✅ 加快构建速度

示例:Go 应用

单阶段构建(不推荐)

dockerfile
FROM golang:1.21
WORKDIR /app
COPY . .
RUN go build -o app .
CMD ["./app"]

最终镜像包含完整的 Go 工具链,体积约 800MB。

多阶段构建(推荐)

dockerfile
# 构建阶段
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .

# 运行阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/app .
CMD ["./app"]

最终镜像只包含编译后的二进制文件,体积约 20MB。

示例:Node.js 应用

dockerfile
# 构建阶段
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 运行阶段
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
EXPOSE 3000
CMD ["node", "dist/index.js"]

命名构建阶段

可以为构建阶段命名,方便引用:

dockerfile
FROM golang:1.21 AS builder
# ...

FROM builder AS test
RUN go test ./...

FROM alpine:latest AS runtime
COPY --from=builder /app/app .

最佳实践

  1. 使用最小基础镜像 - 运行阶段使用 alpinedistroless
  2. 只复制必要文件 - 不要复制源代码和构建工具
  3. 利用构建缓存 - 将依赖安装步骤放在前面

BSFC Tech Pro Tip

生产环境镜像应该尽可能小,这不仅能节省存储空间,还能加快镜像拉取和容器启动速度。


由 BSFC Tech 提供技术支持