Docker 多阶段构建

一、多阶段构建的核心概念

  • 定义 :在单个 Dockerfile 中使用多个 FROM 指令,将构建过程分为多个独立阶段,最终只输出一个精简的最终镜像。

  • 核心思想 :区分构建阶段 (需要编译器、工具链)和运行阶段(只需运行时环境和最终产物),避免将构建工具打包到生产镜像中。


二、传统单阶段构建的问题

问题 说明
镜像臃肿 包含编译器、构建工具、源代码、中间文件等非必要内容
攻击面大 多余软件包可能带有已知漏洞(CVE)
传输部署慢 大镜像浪费带宽和存储,拉取/推送耗时
构建效率低 缺乏阶段隔离,缓存利用不充分

三、多阶段构建的工作原理

  1. 多个 FROM :每个 FROM 开启一个新阶段,可命名(AS stage_name)。

  2. 阶段隔离:前一阶段的文件、环境变量等不会自动传递到下一阶段。

  3. 复制产物 :使用 COPY --from=<阶段名或序号> 从之前阶段复制构建产物到当前阶段。

  4. 最终输出 :Docker 只输出最后一个阶段生成的镜像层。

图示流程

text

复制代码
阶段1(构建): 大型基础镜像 → 安装工具 → 编译/打包 → 生成产物
                        ↓ COPY --from
阶段2(运行): 小型基础镜像 → 复制产物 → 配置运行环境 → 最终镜像

四、关键语法与指令

指令 示例 说明
FROM ... AS name FROM golang:1.21 AS builder 定义构建阶段并命名
COPY --from=name COPY --from=builder /app/server . 从指定阶段复制文件
COPY --from=0 COPY --from=0 /output /target 按阶段索引复制(0 表示第一个 FROM)

五、多阶段构建的主要优点

  1. 显著减小镜像体积:通常可减少 50%~90% 大小。

  2. 提高安全性:去除构建工具和临时文件,减少漏洞暴露面。

  3. 简化构建流程:无需外部脚本,所有步骤在一个 Dockerfile 中完成。

  4. 更快的传输部署:小镜像在 CI/CD 和云环境中拉取/推送更快。

  5. 更好的缓存利用:各阶段可独立缓存,依赖未变时跳过安装步骤。


六、各技术栈的典型示例

1. Go 应用

dockerfile

复制代码
# 构建阶段
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server .

# 运行阶段
FROM alpine:3.18
COPY --from=builder /app/server .
CMD ["./server"]
  • 效果:从 ~1GB 降至 ~15MB

2. Java (Spring Boot)

dockerfile

复制代码
FROM maven:3.8-openjdk-11 AS builder
...
FROM openjdk:11-jre-slim
COPY --from=builder /app/target/*.jar app.jar
  • 效果:典型从 650MB 降至 85MB

3. Node.js 前端

dockerfile

复制代码
FROM node:20 AS builder
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

4. PHP Laravel(四阶段复杂案例)

  • 阶段1composer 镜像安装 PHP 依赖(只安装生产依赖)

  • 阶段2node:alpine 构建前端资源

  • 阶段3php-fpm-alpine 准备应用代码、PHP 扩展、权限设置

  • 阶段4nginx:alpine 最终运行镜像

  • 优化成效:镜像大小从 750MB+ 降至 250MB,CVE 漏洞减少 85%


七、最佳实践与技巧

  • 利用缓存 :先复制依赖文件(如 go.modcomposer.jsonpackage.json),后复制源码。

  • 最小化基础镜像 :运行阶段优先使用 alpinedistrolessscratch

  • 合并 RUN 命令 :减少镜像层数,并清理临时文件(rm -rf /var/lib/apt/lists/*)。

  • 禁用不必要的功能 :如 Go 中 CGO_ENABLED=0 生成静态二进制,避免依赖 glibc。

  • 只复制必要文件 :使用 COPY --from 精确复制二进制、JAR 包、静态资源等,不复制源码或中间文件。

  • 生产环境加固:设置健康检查、使用非 root 用户、配置安全选项(如隐藏版本号、禁用危险函数)。


八、总结对比

指标 单阶段构建 多阶段构建
镜像大小 大(含构建工具) 小(仅运行时+产物)
构建速度 慢(全量构建) 快(增量缓存)
安全性 低(攻击面大) 高(最小依赖)
部署效率 低(传输慢) 高(镜像小)

适用场景:任何需要编译、打包、资源处理的应用程序(Go、Java、Rust、C++、前端、PHP 等)。

多阶段构建是 Docker 官方推荐的镜像优化最佳实践,应作为生产环境容器化的默认方案。

相关推荐
用户03284722207014 小时前
如何搭建本地yum源(上)
运维
武子康15 小时前
调查研究-183 Apple container:Mac 上用轻量 VM 跑 Linux 容器,Swift 会改写本地容器体验吗?
docker·容器·apple
大树884 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质4 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工4 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
Alsn864 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker
酣大智4 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_4 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉4 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造