本文最后更新于11 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
一、为什么要用 Docker 多阶段构建(背景)
在 Java 项目容器化过程中,常见流程是:
mvn clean package → 生成 jar → java -jar 运行
如果我们直接在一个镜像中完成构建 + 运行,会带来几个问题:
- ❌ 镜像中包含 Maven、JDK、源码、依赖缓存
- ❌ 镜像体积大(400MB+)
- ❌ 构建工具暴露在运行环境中(安全风险)
- ❌ 启动慢、攻击面大
**Docker 多阶段构建(Multi-stage Build)**就是为了解决这些问题而生的。
二、单阶段构建的问题回顾(你的 back:v1)
Dockerfile(单阶段)
FROM maven:3.9.8-eclipse-temurin-11
WORKDIR /app COPY pom.xml ./
COPY src ./src RUN mvn clean package -DskipTests
EXPOSE 5000
CMD ["java","-jar","/app/target/app.jar"]
特点
- Maven + JDK + jar 都在一个镜像中
docker images back:v1体积 ≈411MB
问题总结
| 问题 | 说明 |
|---|---|
| 镜像臃肿 | Maven 镜像本身就 300MB+ |
| 不安全 | 构建工具暴露在生产容器 |
| 不专业 | 不符合生产环境最小化原则 |
三、Docker 多阶段构建的核心思想(重点)
构建和运行,分离在不同阶段
- 第一阶段:只负责“编译”
- 第二阶段:只负责“运行”
Docker 会:
- 只保留最后一个阶段的内容
- 前面阶段的 Maven / 源码 / 缓存不会进入最终镜像
四、多阶段 Dockerfile 结构解析(你的 back:v2)
多阶段 Dockerfile(标准写法)
# ---------- Stage 1:构建阶段 ----------
FROM maven:3.9.8-eclipse-temurin-11 AS build
WORKDIR /app COPY pom.xml ./
COPY src ./src
RUN mvn clean package -DskipTests
———- Stage 2:运行阶段 ———-
FROM eclipse-temurin:11-jre
WORKDIR /app
COPY --from=build /app/target/*.jar /app/app.jar
EXPOSE 5000
CMD ["java","-jar","/app/app.jar"]`
关键知识点逐条解释(⭐重点)
1️⃣AS build
FROM maven:... AS build
- 给第一阶段起名:
build - 后面可以通过
--from=build精确引用它的产物
2️⃣ 构建阶段只做一件事:产出 jar
RUN mvn clean package -DskipTests
- Maven、源码、依赖都留在 build 阶段
- 最终只需要
target/*.jar
3️⃣ 运行阶段只复制 jar(最重要)
COPY --from=build /app/target/*.jar /app/app.jar
这行代码是多阶段构建的灵魂:
- 只把 jar 拷贝到最终镜像
- 不带 Maven
- 不带源码
- 不带
.m2缓存
4️⃣ 最终镜像只保留 JRE
FROM eclipse-temurin:11-jre
- 比 maven 镜像小很多
- 只用于运行 Java
- 启动更快,攻击面更小
五、构建结果对比(非常适合写进笔记)
| 镜像 | 构建方式 | 体积 |
|---|---|---|
| back:v1 | 单阶段(Maven + 运行) | ≈411MB |
| back:v2 | 多阶段(Build → JRE) | ≈147MB |
体积减少约 65%+
六、完整验证流程总结(你实际做的步骤)
1️⃣ 构建前端镜像
cd fronted docker build -t front:v1 .
2️⃣ 构建后端镜像(多阶段)
cd personal-memo docker build -t back:v2 .
3️⃣ docker-compose 组合运行
services:
backend:
image: back:v2
container_name: backend
ports:
- "5000:5000"
frontend:
image: front:v1
container_name: frontend
ports:
- "8080:80"
depends_on:
- backend
启动:
docker-compose up -d
4️⃣ 功能验证
- 前端页面:
http://<server-ip>:8080 - 后端接口:通过 Nginx
/api/*反向代理 - 登录、业务功能正常
5️⃣ 镜像体积验证
docker images | grep back
确认:
back:v2明显小于back:v1