Docker 的多阶段构建(Multi-Stage Builds)是一个功能强大的特性,用于优化 Docker 镜像的构建过程。它允许你在 Dockerfile
中使用多个 FROM
指令来创建不同的构建阶段,从而将构建过程分成多个阶段。每个阶段都可以使用不同的基础镜像,最终只将所需的内容从构建阶段传递到最终镜像中。
主要优势
- 减少镜像体积:通过仅将最终结果从构建过程中复制到最终镜像中,避免了将中间构建依赖项和构建工具包含在最终镜像中。
- 提高构建速度:中间镜像层可以被缓存,从而加快构建过程,尤其是当构建流程中有多个阶段时。
- 简化 Dockerfile:使得
Dockerfile
更加简洁和易于维护。
基本用法
以下是一个多阶段构建的示例 Dockerfile
,展示了如何使用两个阶段来构建一个 Node.js
应用程序。
# 第一阶段: 构建阶段
FROM node:18 AS build
# 设置工作目录
WORKDIR /app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm install
# 复制源代码
COPY . .
# 执行构建命令
RUN npm run build
# 第二阶段: 生产阶段
FROM node:18-slim
# 设置工作目录
WORKDIR /app
# 复制构建结果到生产镜像
COPY --from=build /app/dist /app/dist
# 复制生产环境依赖
COPY --from=build /app/package*.json ./
RUN npm install --only=production
# 启动应用
CMD ["node", "dist/index.js"]
- 构建阶段(build):
使用完整的node:18
镜像,进行依赖安装和应用构建。
设置工作目录 /app。
复制package.json
和package-lock.json
,安装依赖。
复制应用源代码并运行构建命令。 - 生产阶段(生产环境):
使用更轻量级的node:18-slim
镜像作为生产环境镜像。
只将构建结果从构建阶段复制到生产镜像中。
仅安装生产环境所需的依赖。
设置容器的启动命令。
多阶段构建的高级用法
- 构建工具分离:可以将构建工具(如编译器、构建系统等)和生产环境的应用分开,减少生产镜像的大小。
- 多个构建阶段:可以添加多个构建阶段来处理不同的构建任务,例如测试、打包等。
# 第一阶段: 构建和测试阶段
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
RUN npm test # 运行测试
# 第二阶段: 生产阶段
FROM node:18-slim
WORKDIR /app
COPY --from=build /app/dist /app/dist
COPY --from=build /app/package*.json ./
RUN npm install --only=production
CMD ["node", "dist/index.js"]
常见问题
- 跨阶段复制:使用
COPY --from=<stage_name>
指令可以从一个构建阶段复制文件到另一个阶段。在多阶段构建中,确保指定正确的阶段名称和路径。 - 缓存:Docker 会缓存每个构建步骤,利用这一点可以加速构建过程。确保
Dockerfile
的顺序能利用好缓存。 - 镜像大小:多阶段构建有助于减小最终镜像的大小,但还是需要注意镜像中的实际内容,避免将不必要的文件和依赖包含在内。