Docker 分阶段构建
Docker 分阶段构建(Multi-stage Build)是一种高效的镜像构建技术,允许在一个 Dockerfile 中使用多个构建阶段,每个阶段可以使用不同的基础镜像,最终只保留需要的文件,从而显著减小镜像体积。以下是分阶段构建的核心概念和示例:
为什么使用分阶段构建?
- 减小镜像体积:最终镜像只包含运行时所需的文件,不包含构建工具和临时文件。
- 简化 Dockerfile:无需手动清理中间文件,每个阶段专注于特定任务。
- 提高安全性:生产环境镜像不包含不必要的构建依赖,降低安全风险。
基本语法
使用 FROM <image> AS <stage-name>
定义多个构建阶段:
# 第一阶段:构建应用(使用较大的基础镜像)
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build# 第二阶段:运行应用(使用轻量级基础镜像)
FROM node:18-slim
WORKDIR /app
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/dist ./dist # 只复制构建结果
RUN npm install --production # 只安装生产依赖
CMD ["node", "dist/main.js"]
关键点说明
- 阶段命名:使用
AS <stage-name>
为每个阶段命名,便于后续引用。 - 文件复制:使用
COPY --from=<stage-name>
从之前的阶段复制文件。 - 基础镜像选择:构建阶段可使用完整的 SDK 镜像,运行阶段使用轻量级的运行时镜像(如
alpine
或slim
)。
常见场景示例
1. Go 应用分阶段构建
# 构建阶段
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp# 运行阶段
FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]
2. Java Spring Boot 应用分阶段构建
# 构建阶段
FROM maven:3.8.6-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests# 运行阶段
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/target/myapp.jar .
CMD ["java", "-jar", "myapp.jar"]
高级技巧
- 多阶段复用:一个阶段可以从多个之前的阶段复制文件。
- 条件构建:使用
--target
参数指定构建到特定阶段(用于调试):docker build --target builder -t myapp:builder .
- 缓存优化:合理安排
COPY
指令顺序,利用 Docker 构建缓存。
注意事项
- 每个
FROM
语句都会创建一个新阶段,之前阶段的环境不会延续。 - 最终镜像体积只包含最后一个阶段的内容。
- 分阶段构建不会影响构建速度,但能大幅减小镜像体积。
通过分阶段构建,你可以创建更高效、更安全的 Docker 镜像,同时保持开发流程的简洁性。