【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/layers
                          https://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 extract

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"]

假设上述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.mfbz.cn/a/602755.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕业设计Python+Vue.js天气预测系统 中国气象质量采集与可视化 天气数据分析 天气可视化 天气大数据 天气爬虫 大数据毕业设计

摘要 随着科技技术的不断发展&#xff0c;人民物质生活质量不断提高&#xff0c;我们越来越关注身边的气象、空气等地理环境。对于普通居民我们会选择合适的气象进行出游&#xff0c;提高精神层面的生活质量&#xff1b;对于企业会关注气象变换状况&#xff0c;来定制相关的生产…

使用.NET8实现Web API

目录 1、环境准备1.1、从官网下载 及安装VS2022社区版1.2、下载及安装asp.net core的运行时及IIS Module 2、WebAPI工程创建2.1 创建API服务2.2 推荐的库2.2.1 数据库篇2.2.1.1、 SQLSugar2.2.1.2、 OracleAccess 2.2.2、IOC篇2.2.2.1、autofac2.2.2.2、 2.2.3、日志记录篇2.2.…

MY SQL 实验一:

一、实验目的 通过实验了解MYSQL数据库服务器的基本架构及基本的使用方法。 二、实验原理、条件 本实验采用著名的开源数据库软件MYSQL 作为实验平台。MYSQL有多种版本&#xff0c;常用的是服务器版。数据库引擎是用于存储、处理和保护数据的核心服务。MYSQL有多个数据库引擎&a…

【北京迅为】《iTOP-3588开发板快速烧写手册》-第4章 烧写器RKDevTool常用功能

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

规培报名身份证上传怎么小于500k?这几个方法试试看

大家都知道在规培报名的时候&#xff0c;是需要上传一些自己的个人信息资料到平台上的&#xff0c;其中身份证照片是比较重要的一项&#xff0c;我们自己拍的身份证照片大小有时候可能不符合网站的规定&#xff0c;需要去做一些图片修改调整&#xff0c;比如图片你压缩&#xf…

【自动驾驶|毫米波雷达】初识毫米波雷达射频前端硬件

第一次更新&#xff1a;2024/5/4 目录 整体概述 混频器&#xff08;MIXER&#xff09; 低通滤波器&#xff08;LPF&#xff1a;Low-Pass filter&#xff09; 数模转换器&#xff08;ADC&#xff1a;Analog to Digital Converter&#xff09; 毫米波雷达功能框图 整体概述 完…

1072 开学寄语(测试点2)

solution 测试点2:物品编号可能不足四位&#xff0c;高位需补0 #include<iostream> #include<string> using namespace std; const int maxn 1e5; int flag[maxn] {0}; int main(){int n, m, k, cnt 0, cnt1 0, have, x;string id;cin >> n >> m…

基于STM32的智能垃圾桶设计(论文+源码)_kaic

基于STM32的智能垃圾桶设计 摘 要 随着社会科学技术的迅猛进展&#xff0c;人们的生活质量和速度也在不断提高。然而&#xff0c;大多数传统的家庭垃圾桶已经过时且缺乏创新&#xff0c;缺乏人性化设计。它们使用起来不方便、不卫生&#xff0c;所有的生活和废物垃圾都被混合…

跨平台桌面客户端开发框架

跨平台桌面客户端开发框架允许开发者创建能够在多个操作系统上运行的桌面应用程序。以下是一些流行的跨平台桌面客户端开发框架。这些框架各有优势&#xff0c;选择哪个框架取决于项目需求、团队的技术栈以及对特定特性的偏好。 1.Electron &#xff1a; 使用JavaScript, HTML…

融知财经:期权期货及其他衍生产品

期权、期货及其他衍生产品是金融市场中用于管理风险和进行投机的金融工具。这些衍生产品的价值依赖于一个或多个基础资产&#xff0c;如股票、商品、利率、汇率等。以下是关于这些衍生产品的一些基本介绍&#xff1a; 1、期货&#xff08;Futures&#xff09;&#xff1a;期货是…

5月7号(信息差)

&#x1f30d;首次&#xff0c;西湖大学用蛋白质语言模型定向改造碱基编辑器&#xff0c;登Cell子刊 https://www.jiqizhixin.com/articles/2024-05-07-10 &#x1f384; 哈马斯宣布同意停火提议 https://finance.eastmoney.com/a/202405073067687785.html ✨ 中国将对…

数据结构学习:栈(详细讲解)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C语言基本概念 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f697;1.对栈概念理解&#xff1a; &a…

【Debug日记】albumentations包安装失败解决方案

直接pip安装pip install albumentations 报错&#xff1a; ERROR: Command errored out with exit status 1:command: D:\anaconda3\envs\pytorch\python.exe D:\anaconda3\envs\pytorch\lib\site-packages\pip\_vendor\pep517\in_process\_in_process.py build_wheel C:\Users…

【编程题-错题集】连续子数组最大和(动态规划 - 线性 dp)

牛客对应题目链接&#xff1a;连续子数组最大和_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 简单线性 dp。 1、状态表示 dp[i] 表示&#xff1a;以 i 位置为结尾的所有子数组中&#xff0c;最大和是多少。 2、状态转移方程 dp[i] max(dp[i - 1] arr[i], arr[i]) 3、返回…

Sarcasm detection论文解析 |使用 BERT 进行中间任务迁移学习的刺检测

论文地址 论文地址&#xff1a;https://www.mdpi.com/2227-7390/10/5/844#/ github&#xff1a;edosavini/TransferBertSarcasm (github.com) 论文首页 笔记框架 使用 BERT 进行中间任务迁移学习的讽刺检测 &#x1f4c5;出版年份:2022 &#x1f4d6;出版期刊:Mathematics &…

[C/C++] -- 装饰器模式

装饰器模式是一种结构型设计模式&#xff0c;它允许在不改变原始对象的基础上动态地扩展其功能。这种模式通过将对象包装在装饰器类的对象中来实现&#xff0c;每个装饰器对象都包含一个原始对象&#xff0c;并可以在调用原始对象的方法之前或之后执行一些额外的操作。 装饰器…

炫龙电脑数据恢复方法有哪些?4个常用方法大放送

随着科技的不断发展&#xff0c;电脑已成为我们日常生活中不可或缺的一部分。然而&#xff0c;无论是由于操作失误、病毒感染、系统崩溃还是硬件故障&#xff0c;数据丢失都可能是每个电脑用户都可能面临的问题。对于使用炫龙电脑的用户来说&#xff0c;了解并掌握一些基本的数…

webassembly入门详解(C++)

一、环境配置 环境说明,操作系统为window操作系统。 1.1 下载和安装python 下载 需要python版本至少3.6版本 python下载地址:https://www.python.org/getit/ 安装 检测安装结果 win+R组合键->cmd->输入python->回车 1.2 下载和安装emsdk 下载 下载地址:https://gi…

这个Python库Streamlit,5分钟内搭建可视化WEB应用

在数据科学的世界里&#xff0c;将分析结果快速、直观地呈现给非技术背景的决策者&#xff0c;是一项重要的技能。而Streamlit&#xff0c;这个开源的Python库&#xff0c;正是为此而生。它允许数据科学家和工程师通过少量的代码&#xff0c;快速创建和分享数据应用。今天&…

OpenAI推出DALL·E 3识别器、媒体管理器

5月8日&#xff0c;OpenAI在官网宣布&#xff0c;将推出面向其文生图模型DALLE 3 的内容识别器&#xff0c;以及一个媒体管理器。 随着ChatGPT、DALLE 3等生成式AI产品被大量应用在实际业务中&#xff0c;人们越来越难分辨AI和人类创建内容的区别&#xff0c;这个识别器可以帮…
最新文章