【docker】Spring Boot Layered Jar:优化Docker镜像构建与部署的新方案

一、Spring Boot Layered Jar优化Docker构建

Spring Boot Layered Jar 是一种特殊的 Jar 包格式,由 Spring Boot 2.3 及以上版本提供。这种格式主要是为了优化 Docker 镜像的构建和部署过程。以下是关于 Spring Boot Layered Jar 的详细解释:

1. 分层结构

  • 背景:传统的 Spring Boot Jar 包是一个包含所有依赖、资源和应用程序代码的“胖”Jar(fat Jar)。这种结构在每次代码变更时都需要重新构建和上传整个 Jar 包,这会导致存储和时间的浪费,特别是在网络速度较慢的情况下。
  • Layered Jar:为了解决这个问题,Spring Boot 引入了 Layered Jar 的概念。Layered Jar 将应用程序的不同部分(如依赖库、Spring Boot 加载器、应用程序代码等)分隔到不同的层中。这样,当应用程序代码发生变化时,只需要重新构建和上传相应的层,而不是整个 Jar 包。

2. 如何使用

  • 配置:在 Maven 项目中,要启用 Layered Jar,只需在 pom.xml 文件中为 spring-boot-maven-plugin 插件添加 <layers><enabled>true</enabled></layers> 配置。
  • 打包:启用 Layered Jar 后,使用 Maven 打包命令(如 mvn package)将生成一个包含多个层的 Jar 文件。这个文件可以使用 java -jar 命令直接运行,就像传统的 Jar 包一样。
  • Docker 镜像构建:当使用 Docker 构建镜像时,Layered Jar 的优势更加明显。由于 Docker 镜像也是分层的,因此可以利用 Layered Jar 的分层特性来优化镜像的构建过程。这样,当应用程序代码发生变化时,只需要重新构建包含代码变更的层,而不是整个镜像。

3. 优势

  • 提高构建效率:由于只需要重新构建和上传变更的层,因此可以大大减少构建和部署时间。
  • 节省存储空间:分层结构避免了每次代码变更都需要重新上传整个 Jar 包的情况,从而节省了存储空间。
  • 更好的缓存利用:Docker 可以更有效地利用缓存机制,因为未变更的层可以从缓存中直接获取,而不需要重新构建。

4. 注意事项

  • 兼容性:Layered Jar 需要 Spring Boot 2.3 及以上版本才支持。同时,为了充分利用 Layered Jar 的优势,建议使用较新版本的 Docker 和相关的构建工具。
  • 配置细节:虽然启用 Layered Jar 只需要简单的配置更改,但为了获得最佳效果,可能需要根据项目的具体情况调整配置参数(如层的划分方式等)。

总的来说,Spring Boot Layered Jar 是一种优化 Docker 镜像构建和部署过程的解决方案。它通过分层结构减少了每次代码变更时需要重新构建和上传的数据量,从而提高了构建效率并节省了存储空间。

二、什么是 Layered Jar or War

一个 repackaged 的jar文件在BOOT-INF/classesBOOT-INF/lib中分别包含应用程序的类和依赖项。同样,一个可执行的war文件在WEB-INF/classes中包含应用程序的类,在WEB-INF/lib和WEB-INF/lib-provided中包含依赖项。对于那些需要从jar或war的内容构建Docker镜像的情况,能够进一步分离这些目录以便将它们写入不同的层是很有用的。

分层归档使用与普通重新打包的jar或war相同的布局,但包括一个描述每一层的附加元数据文件(layers.idx)。

默认情况下,定义了以下层:

  • dependencies:用于不包含SNAPSHOT版本的任何依赖项。
  • spring-boot-loader:用于加载器类。
  • snapshot-dependencies:用于包含SNAPSHOT版本的任何依赖项。
  • application:用于本地模块依赖项、应用程序类和资源。

模块依赖项是通过查看当前构建的所有模块来识别的。如果模块依赖项只能因为已经安装到Maven的本地缓存中而得到解析,并且它不是当前构建的一部分,那么它将被识别为常规依赖项。

层的顺序很重要,因为它决定了当应用程序的某一部分发生变化时,之前的层被缓存的可能性有多大。默认顺序是dependenciesspring-boot-loadersnapshot-dependenciesapplication。最不可能改变的内容应该首先添加,其次是更有可能改变的层。

默认情况下,打包的jar文件中包括layers.idx文件。要禁用此功能,您可以按以下方式进行操作:

<project><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><layers><enabled>false</enabled></layers></configuration></plugin></plugins></build>
</project>

通过将这些内容写入不同的层,可以更有效地利用Docker的缓存机制,从而提高构建效率。

三、自定义分层配置

根据您的应用程序需求,您可能想要调整如何创建层并添加新层。这可以通过使用一个单独的配置文件来完成,该文件的注册方式如下所示:

<project><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><layers><enabled>true</enabled><configuration>${project.basedir}/src/layers.xml</configuration></layers></configuration></plugin></plugins></build>
</project>

配置文件描述了如何将归档文件分离成不同的层,以及这些层的顺序。以下示例展示了如何明确定义上述默认顺序:

<layers xmlns="http://www.springframework.org/schema/boot/layers"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/boot/layershttps://www.springframework.org/schema/boot/layers/layers-3.2.xsd"><application><into layer="spring-boot-loader"><include>org/springframework/boot/loader/**</include></into><into layer="application" /></application><dependencies><into layer="application"><includeModuleDependencies /></into><into layer="snapshot-dependencies"><include>*:*:*SNAPSHOT</include></into><into layer="dependencies" /></dependencies><layerOrder><layer>dependencies</layer><layer>spring-boot-loader</layer><layer>snapshot-dependencies</layer><layer>application</layer></layerOrder>
</layers>

layers XML格式在三个部分中定义:

  • <application>块定义了如何将应用程序类和资源进行分层。

  • <dependencies>块定义了如何将依赖项进行分层。

  • <layerOrder>块定义了层应该写入的顺序。

<application><dependencies>部分中,嵌套的<into>块用于为层声明内容。这些块按照从上到下的定义顺序进行评估。任何未被前面的块声明的内容仍然可供后续块考虑。

<into>块使用嵌套的<include><exclude>元素来声明内容。<application>部分使用Ant风格的路径匹配来定义包含/排除表达式。<dependencies>部分使用group:artifact[:version]模式。它还提供了<includeModuleDependencies /><excludeModuleDependencies />元素,这些元素可用于包含或排除本地模块依赖项。

如果没有定义<include>,那么所有内容(未被先前的块声明的内容)都会被考虑进去。

如果没有定义<exclude>,那么就不会应用任何排除规则。

从上面的<dependencies>示例中,我们可以看到,第一个<into>将为application.layer声明所有的模块依赖项。下一个<into>将为snapshot-dependencies层声明所有的SNAPSHOT依赖项。最后一个<into>将声明剩下的任何内容(在这种情况下,是指任何非SNAPSHOT的依赖项)为dependencies层。

<application>块有类似的规则。首先为spring-boot-loader层声明org/springframework/boot/loader/**的内容。然后为application层声明任何剩余的类和资源。

注意<into>块的定义顺序通常与层的写入顺序不同。因此,必须始终包含<layerOrder>元素,并且必须涵盖所有由<into>块引用的层。

四、在Dockerfile中使用layer构建镜像

1、如何在Dockerfile中使用

我们将使用分层特性来创建一个优化的Docker镜像。当您创建一个包含层索引文件的jar包时,spring-boot-jarmode-layertools jar将被添加为您jar的依赖项。只要该jar在类路径上,您就可以在特殊模式下启动应用程序,该模式允许引导代码运行与您的应用程序完全不同的东西,例如,提取层的东西。

layertools模式不能与包含启动脚本的完全可执行的Spring Boot归档文件一起使用。在构建打算与layertools一起使用的jar文件时,应禁用启动脚本配置。

以下是如何以layertools jar模式启动jar包:

$ java -Djarmode=layertools -jar my-app.jar

这将提供以下输出:

使用方法:java -Djarmode=layertools -jar my-app.jar可用命令:list     列出可从jar中提取的层extract  从jar中提取层以创建镜像help     有关任何命令的帮助

extract命令可用于轻松将应用程序拆分为要添加到Dockerfile的层。
以下是一个使用jarmode的Dockerfile示例。

FROM eclipse-temurin:17-jre as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extractFROM eclipse-temurin:17-jre
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]

假设上述Dockerfile位于当前目录中,您的Docker镜像可以使用docker build命令构建,或者选择指定应用程序jar的路径,如下例所示:

$ docker build --build-arg JAR_FILE=path/to/myapp.jar .

这是一个多阶段的Dockerfile。builder阶段提取稍后需要的目录。每个COPY命令都与jarmode提取的层相关。

当然,Dockerfile可以在不使用jarmode的情况下编写。您可以使用unzipmv的某种组合将内容移动到正确的层,但jarmode简化了这一过程。

2、构建步骤说明

第一阶段:builder

FROM eclipse-temurin:17-jre as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
  • FROM eclipse-temurin:17-jre as builder:这行代码开始了第一阶段,命名为 builder。它使用了一个包含 Java 17 JRE 的基础镜像 eclipse-temurin:17-jre
  • WORKDIR application:设置工作目录为 application
  • ARG JAR_FILE=target/*.jar:定义了一个参数 JAR_FILE,默认值为 target/*.jar,这意味着它会尝试复制 target 目录下的任何 JAR 文件。
  • COPY ${JAR_FILE} application.jar:将构建好的 JAR 文件复制到镜像的 application.jar
  • RUN java -Djarmode=layertools -jar application.jar extract:这行命令使用 Spring Boot 的 layertools 功能来解压 JAR 文件的不同层。允许将 JAR 文件分解为不同的层,以便于在 Docker 镜像中更有效地缓存和复用这些层。

第二阶段:生产镜像

FROM eclipse-temurin:17-jre
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
  • FROM eclipse-temurin:17-jre:这行代码开始了第二阶段(也是最终的生产镜像阶段),它同样使用了 eclipse-temurin:17-jre 作为基础镜像。
  • WORKDIR application:再次设置工作目录为 application
  • 接下来的四个 COPY 指令都从 builder 阶段复制了之前通过 layertools extract 分解出来的不同层到当前阶段。这样做的好处是,如果这些层在未来的构建中没有变化,Docker 可以利用缓存机制,避免重复构建这些层,从而提高构建效率。
    • COPY --from=builder application/dependencies/ ./:复制依赖项层。
    • COPY --from=builder application/spring-boot-loader/ ./:复制 Spring Boot 加载器层。
    • COPY --from=builder application/snapshot-dependencies/ ./:如果有快照依赖项,则复制它们。
    • COPY --from=builder application/application/ ./:复制应用程序本身的文件和资源。
  • ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]:设置容器的入口点,以便在容器启动时运行 Spring Boot 应用程序。

通过这种方式,Dockerfile 利用了多阶段构建和 Spring Boot 的层工具来创建一个优化了大小和构建时间的 Docker 镜像。

参考

  • packaging.layers
  • container-images

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/8227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么扫描二维码看图片?在线制作图片二维码的方法

随着现在二维码的广泛使用&#xff0c;用这个方式来展现内容的情况越来越多&#xff0c;比如扫码看图就是一种很常见的一种类型。将图片生成二维码后通过扫码来调取云端存储的图片查看&#xff0c;这样可以一次预览多张图片并且不会占据内存&#xff0c;能够快速的实现图片内容…

PyPI 与 GitHub 的双因素认证 | 2FA 配置指南

唠唠闲话 最近登录 GitHub 一直提示设置双重验证。除此之外&#xff0c;开发 Python 包常用的平台—— PyPI &#xff0c;也宣布从今年开始强制启用双因素认证&#xff08;2FA&#xff09;。这一变化虽然在提高安全性方面起到了积极作用&#xff0c;但也给日常工作带来了麻烦。…

P1164 小A点菜

题目描述: 不过 uim 由于买了一些书&#xff0c;口袋里只剩 &#x1d440;M 元 (&#x1d440;≤10000)(M≤10000)。 餐馆虽低端&#xff0c;但是菜品种类不少&#xff0c;有 &#x1d441;N 种 (&#x1d441;≤100)(N≤100)&#xff0c;第 &#x1d456;i 种卖 &#x1d44…

情感聊天赛道用al制作一分钟一条视频无脑玩法日入500+

详情介绍 这个赛道是用al快速制作情感故事聊天 原理就是用爆款的文案 al生成情感聊天视频全网独家赛道不拥挤 这个赛道几乎没人做一片蓝海 视频号分成计划 抖音中视频都可以做 建议做视频号创作者分成计划 单价高事少 视频号的平均用户年龄都是比较大的 对于这种情感故事的…

【UE+MQTT】Mqtt Client插件使用记录

步骤 1. 在虚幻商城中下载“Mqtt Client”插件 插件地址&#xff1a;https://www.unrealengine.com/marketplace/zh-CN/product/34cbcaef7a664451a886dba37b4769bc?sessionInvalidatedtrue 文档地址&#xff1a;[虚幻引擎] DT Mqtt 插件详细说明 – DT 2. 在虚幻编辑器中确…

CSS 预处理器:stylus运用详解

文章目录 一、stylus简介Stylus 的主要特性引入 Stylus1. 安装 Stylus2. 配置 webpack3. 编写 Stylus 文件4. 在项目中引入 Stylus 文件 总结 二、stylus常见问题三、stylus运用案例四、stylus优缺点五、热门文章 一、stylus简介 Stylus 是一个强大的 CSS 预处理器&#xff0c…

菜鸡学习netty源码(四)—— EventLoopGroup

1.概述 我们前面进行过分析,channel为netty网络操作的抽象类,EventLoop负责处理注册到其上的Channel处理的I/O事件;EventLoopGroup是一个EventLoop的分组,它可以获取到一个或者多个的EventLoop对象。 2.类关系图 NioEventLoopGroup的类继承图,蓝色部分为对应的java类,绿…

正点原子imx6ull内核移植网络驱动修改无法出现两个网络端口

重点1&#xff1a;手册上让我们在&iomuxc_snvs节点中做点添加网络复位信息&#xff0c;我们这里不需要做&#xff0c;直接下一步。 这里与手册不同&#xff0c;这里直接像我这样将pinctrl_enet2和pinctrl_enet1中对最后两行做修改和添加。直接将复位引脚的配置加入这个节点…

TalkingGaussian:基于高斯溅射的结构保持3D说话人头合成

TalkingGaussian: Structure-Persistent 3D Talking Head Synthesis via Gaussian Splatting TalkingGaussian&#xff1a;基于高斯溅射的结构保持3D说话人头合成 Jiahe Abstract 摘要 TalkingGaussian: Structure-Persistent 3D Talking Head Synthes…

Paxos算法和ZooKeeper使用的Zab(ZooKeeper Atomic Broadcast)算法

Paxos算法和ZooKeeper使用的Zab&#xff08;ZooKeeper Atomic Broadcast&#xff09;算法都是分布式一致性算法&#xff0c;用于在分布式系统中达成一致性决策。尽管它们的目标相同&#xff0c;但在设计和实现上存在一些区别。 Paxos算法 设计目的&#xff1a;Paxos算法是一种…

基于树莓派的六足机器人方案设计+源代码+工程内容说明

文章目录 源代码下载地址项目介绍项目内容说明简单预览 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 项目内容说明 hardware为项目相关硬件设计 机械结构为六足机器人的3d建模工程&#xff0c;包括本体和云台遥控器在ESP32最小开发板上集成了MPU605…

[C/C++] -- 适配器模式

适配器模式是一种结构型设计模式&#xff0c;它允许接口不兼容的类能够相互合作。这种模式允许将一个类的接口转换成另一个类的接口&#xff0c;从而使得原本由于接口不匹配而无法在一起工作的类能够协同工作。 适配器模式通常用于以下情况&#xff1a; 系统需要使用现有的类…

留学资讯 | 曼大突然官宣接受雅思单科重考!单科重考体验大揭秘!

雅思单科重考于昨日&#xff08;5月6日&#xff09;进行了大陆地区的首场考试&#xff0c;不少烤鸭都在观望状态&#xff0c;表示&#xff1a;虽然我很心动&#xff0c;但是学校们可不心动&#xff01;&#xff01; 别急&#xff01;好消息这不就来了&#xff01;曼大官网明确表…

PaddleOCR使用

最近在项目过程中需要用到文字识别的能力&#xff0c;之前没有接触过。需要对现有的开源能力进行调研和学习。 1. 基本概念 1.1 PaddlePaddle PaddlePaddle 是一个由百度开源&#xff0c;基于 Python 的深度学习框架。PaddlePaddle 针对不同的硬件环境提供了不同的安装包或安…

vue导出大量数据的表格方法

我目前的项目导出4万7数据没问题 先安装 npm install -S file-saver npm install xlsx0.16.0 -S npm install -D script-loader 我使用的版本是"file-saver": “^2.0.5”, “xlsx”: “^0.16.0” 新建Export2Excel.js //Export2Excel.js /* eslint-disable */ requ…

【docker问题记录】虚拟机ubuntu22.04使用docker-compose出现容器不能ping通宿主机所在局域网的情况

直接说结论 原因可能是因为这个版本的ubuntu启动后有时会丢失网络图标此时宿主机相当于没有联网&#xff0c;但是docker相关进程已经启动&#xff0c;使用的是无效的网络配置&#xff0c;哪怕此时再用sudo nmcli networking on启动了网络依然docker-compose容器依然无法联网&a…

stylus详解与引入

Stylus 是一个基于 Node.js 的 CSS 预处理器&#xff0c;它允许开发者以一种类似于脚本的方式编写 CSS 代码&#xff0c;从而创建出更加健壮、动态和富有表现力的样式表。Stylus 的特点包括&#xff1a; 1. 基于 JavaScript&#xff1a;由于 Node.js 是一个 JavaScript 运行环…

使用moveit控制机械臂

在这篇博客中&#xff0c;我们将详细探讨如何利用Python和Robot Operating System&#xff08;ROS&#xff09;配合MoveIt! 控制机械臂执行精确的抓取任务。机械臂技术在工业自动化、医疗服务以及研究领域扮演着越来越关键的角色。本文将通过介绍安装必要的软件、编写控制脚本以…

MP4视频转MOV电影视频格式的方法?汇帮视频格式转换器帮你实现一键转MOV

有关MOV视频格式的介绍&#xff1a; MOV视频是一种多媒体文件格式&#xff0c;它被广泛用于存储和播放音频和视频内容。这种文件格式由苹果公司开发&#xff0c;作为QuickTime播放器的一部分&#xff0c;用于在Mac OS操作系统上播放多媒体内容。MOV格式的文件通常包含视频、音…

2024年数维杯数学建模A题思路

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…