首页 > Java > java教程 > 正文

在Dockerfile中构建Spring Boot JAR文件:多阶段构建实践

心靈之曲
发布: 2025-10-24 11:24:17
原创
493人浏览过

在Dockerfile中构建Spring Boot JAR文件:多阶段构建实践

本教程旨在解决在dockerfile中构建spring boot应用时,maven打包的jar文件无法正确更新或传递到最终镜像的问题。通过详细讲解docker多阶段构建的原理与实践,我们将展示如何高效地将构建环境与运行环境分离,从而生成更小、更安全的docker镜像,并确保jar文件在运行时阶段的可用性。

引言:理解JAR文件在Dockerfile中的挑战

在将Java或Spring Boot应用程序容器化时,一个常见的需求是将编译好的JAR文件打包到Docker镜像中运行。然而,开发者有时会遇到这样的困惑:在Dockerfile中执行mvn package命令后,生成的JAR文件似乎并未如预期般更新,或者在最终的运行环境中无法找到。这通常发生在尝试将构建逻辑与运行时环境分离,但未能正确实现文件传递时。

传统的单阶段Docker构建方式,即将所有编译、打包和运行的步骤都放在一个Dockerfile中,往往会导致以下问题:

  • 镜像臃肿: 构建工具(如Maven、JDK完整版)、编译中间文件和测试资源等都会被包含在最终镜像中,导致镜像体积庞大。
  • 安全风险: 冗余的构建工具和依赖可能引入不必要的安全漏洞。
  • 构建环境残留: 构建过程中产生的临时文件和缓存占据空间。

当用户尝试优化这一过程,例如在Dockerfile中定义多个FROM指令,但没有正确地将前一阶段的构建产物传递到后一阶段时,就会出现类似“JAR文件未更新”或“找不到JAR文件”的问题。

核心解决方案:Docker多阶段构建

Docker多阶段构建(Multi-stage builds)是解决上述问题的高效且推荐的实践方式。其核心思想是将Docker镜像的构建过程分解为多个独立的阶段,每个阶段使用不同的基础镜像,并专注于特定的任务。

什么是多阶段构建? 多阶段构建允许你在一个Dockerfile中定义多个FROM指令。每个FROM指令都标志着一个新的构建阶段。你可以为每个阶段命名,并在后续阶段中引用这些命名阶段,以便复制它们产生的工件。

多阶段构建的优势:

  • 镜像瘦身: 最终的运行时镜像只包含应用程序及其运行时所需的最小依赖(如JRE),大大减小了镜像体积。
  • 安全性提升: 运行时镜像不包含构建工具和源代码,减少了潜在的攻击面。
  • 构建缓存优化: Docker可以缓存每个阶段的结果,加快后续构建速度。
  • 环境隔离: 构建环境和运行环境完全隔离,避免了不必要的冲突。

实践:构建Spring Boot应用的Dockerfile

我们将通过一个具体的Spring Boot项目示例,演示如何使用多阶段构建来生成一个高效的Docker镜像。

项目结构示例:

Demo
└── src
|    ├── main
|    │   ├── java
|    │       └── com
|    │           └── App.java
|    │               
|    │   
|    └── test
|
├──── Dockerfile
├──── pom.xml
登录后复制

逐步构建多阶段Dockerfile:

即构数智人
即构数智人

即构数智人是由即构科技推出的AI虚拟数字人视频创作平台,支持数字人形象定制、短视频创作、数字人直播等。

即构数智人 36
查看详情 即构数智人

阶段一:构建应用 (Builder Stage)

这个阶段负责编译Java源代码并使用Maven打包成JAR文件。我们使用一个包含JDK和Maven的基础镜像。

# Stage 1: Build the application
# 使用Maven官方镜像作为构建阶段的基础
FROM maven:3.8-jdk-11 as builder

# 设置工作目录,后续所有操作都将在此目录下进行
WORKDIR /app

# 复制Maven项目文件:pom.xml
# 这一步可以利用Docker层缓存,如果pom.xml没有变化,则无需重新下载依赖
COPY pom.xml .

# 复制源代码目录
COPY src ./src

# 执行Maven打包命令,生成JAR文件
# -DskipTests: 在构建Docker镜像时通常跳过测试,以加快构建速度。
#               测试通常在CI/CD流水线的其他阶段执行。
RUN mvn clean package -DskipTests
登录后复制

在这一阶段,Maven会在/app/target目录下生成一个JAR文件。这个JAR文件是我们需要传递给下一个运行阶段的工件。

阶段二:运行应用 (Runtime Stage)

这个阶段负责创建一个轻量级的运行时镜像,只包含JRE和我们上一步构建好的JAR文件。

# Stage 2: Create the final runtime image
# 使用轻量级的OpenJDK JRE镜像作为运行阶段的基础,例如openjdk:11-jre-slim
FROM openjdk:11-jre-slim

# 设置工作目录
WORKDIR /app

# 关键步骤:从前一个阶段(builder)复制JAR文件
# --from=builder: 指定从名为“builder”的阶段复制文件
# /app/target/*.jar: 源路径,表示从builder阶段的/app/target目录下复制所有以.jar结尾的文件
# app.jar: 目标路径,将复制的文件重命名为app.jar并放置在当前阶段的/app目录下
COPY --from=builder /app/target/*.jar app.jar

# 定义容器启动时执行的命令,运行Spring Boot应用
ENTRYPOINT ["java", "-jar", "app.jar"]
登录后复制

COPY --from=builder /app/target/*.jar app.jar 是多阶段构建的核心。它指示Docker从名为builder的阶段中,将/app/target/路径下的所有JAR文件复制到当前阶段的/app/目录下,并将其重命名为app.jar。这样,最终的镜像就只包含了运行应用所需的最小组件。

完整的Dockerfile示例

将以上两个阶段合并,即可得到一个完整的、高效的Spring Boot应用多阶段Dockerfile:

# --- Stage 1: Build the application ---
FROM maven:3.8-jdk-11 as builder

WORKDIR /app

COPY pom.xml .
COPY src ./src

RUN mvn clean package -DskipTests

# --- Stage 2: Create the final runtime image ---
FROM openjdk:11-jre-slim

WORKDIR /app

# Copy the JAR from the 'builder' stage
COPY --from=builder /app/target/*.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]
登录后复制

注意事项与最佳实践

  1. 选择合适的JRE镜像:
    • openjdk:11-jre-slim:比完整JDK镜像小得多,包含运行Java应用所需的一切。
    • openjdk:11-jre-alpine:基于Alpine Linux,镜像体积更小,但可能需要注意glibc与musl libc的兼容性问题(对于大多数Spring Boot应用不是问题)。
  2. Maven依赖缓存: 在构建阶段,可以先复制pom.xml并运行mvn dependency:go-offline来下载所有依赖,然后再复制源代码。这样,如果只有源代码发生变化而pom.xml未变,Docker可以利用缓存,无需重新下载依赖,加速构建。
    FROM maven:3.8-jdk-11 as builder
    WORKDIR /app
    COPY pom.xml .
    RUN mvn dependency:go-offline # 仅下载依赖
    COPY src ./src
    RUN mvn clean package -DskipTests
    登录后复制
  3. 精确指定JAR路径: COPY --from命令中的源路径必须准确指向JAR文件在构建阶段生成的位置。通常是target/*.jar或target/<your-app-name>-<version>.jar。
  4. 环境变量端口 如果应用需要特定的环境变量或暴露端口,应在运行时阶段的Dockerfile中定义,例如EXPOSE 8080。
  5. 日志与调试: 在开发和调试阶段,可以使用更详细的基础镜像或在运行时阶段添加调试工具,但在生产环境中应尽量保持镜像精简。

总结

通过采用Docker多阶段构建,我们能够优雅地解决在Dockerfile中构建Spring Boot应用时JAR文件传递和镜像臃肿的问题。这种方法不仅显著减小了最终Docker镜像的体积,提升了安全性,还优化了构建流程。理解并正确运用COPY --from指令是实现高效Java应用容器化的关键。遵循这些最佳实践,可以确保你的Spring Boot应用在Docker环境中稳定、高效地运行。

以上就是在Dockerfile中构建Spring Boot JAR文件:多阶段构建实践的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号