Spring Boot官方推荐的Docker镜像编译方式-分层jar包

news2025/1/12 3:50:02

目录

  • 参考
  • 一、普通Dockerfile的缺点
  • 二、Docker分层
  • 三、Spring Boot分层
  • 四、实践
    • 核心理论
    • 新建demo工程
      • pom.xml
    • 测试代码
    • 编写Dockerfile
    • 我们在项目根目录执行打包命令
    • 发布docker镜像
    • 修改代码重新发布docker

参考

Spring Boot官方推荐的Docker镜像编译方式-分层jar包
Spring Boot layered(分层) jar 构建docker镜像
Spring Boot独立运行的jar包是如何工作的

一、普通Dockerfile的缺点

我们通常情况下要编译Spring Boot的Docker镜像,一般会写一个下面这样的Dockerfile

FROM openjdk:17
EXPOSE 8080
ARG JAR_FILE=target/my-application.jar #Maven的位置,Gradle为build/libs/my-application.jar 
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

这样做很简单,运行起来也没什么问题,但是它有以下的缺点:

  • 镜像中的jar包是压缩文件,在容器环境中运行需要解压,这需要相当的开销,我们的jar通常要以解压后的形式运行更好。
  • 更新程序后编译新的镜像效率低。Docker镜像的编译时分层构建的,而上面将依赖和程序都放在一个层中。在实际应用中,修改程序编译代码的频率将大大高于依赖的变化,所以我们最好将它们分在不同的层,这样不变的层在docker中可以直接使用缓存。

二、Docker分层

Docker 容器由基本映像和附加层组成。一旦构建了各个层,它们将保持缓存状态,后续构建,就会使用缓存,构建更快

在这里插入图片描述

低层次的变化也会重建较高层次的变化。因此,我们在构建镜像的时候最好将不经常变化的图层保留在底部,而经常变化的图层应该放在顶部。这样就能提高构建docker效率和启动时间。

三、Spring Boot分层

Spring boot 在2.3之后也提供了应用分层,默认分层如下
在这里插入图片描述

这里可以看到应用层是独立一层,我们在修改应用代码的时候就只用构建应用层即可。 spring-boot-loader 、 dependencies 层就可以使用缓存,从而减少docker镜像的创建和启动时间。

四、实践

核心理论

在Spring Boot 2.3之后添加了分层配置我们在打包插件【spring-boot-maven-plugin】中开启分层打包

<layers>
	<enabled>true</enabled>
</layers>
<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<version>${spring-boot.version}</version>
				<configuration>
					<layers>
						<enabled>true</enabled>
					</layers>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

新建demo工程

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<parent>
		<artifactId>spirng-boot-demo</artifactId>
		<groupId>com.demo</groupId>
		<version>1.0.0</version>
	</parent>
	<modelVersion>4.0.0</modelVersion>

	<artifactId>spring-boot-kuberntes-docker</artifactId>

	<properties>
		<maven.compiler.source>11</maven.compiler.source>
		<maven.compiler.target>11</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<version>${spring-boot.version}</version>
				<configuration>
					<layers>
						<enabled>true</enabled>
					</layers>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

</project>

测试代码

测试代码
Application
@SpringBootApplication
public class  Application  { 

	public  static  void  main(String[] args)  { 
		TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
		SpringApplication.run(Application.class, args);
	}
}
...
...
TestController
@RestController
@RequestMapping
public class  TestController  { 

	@GetMapping("test")
	public String test() { 
		return "hello docker image";
	}
}

编写Dockerfile

from openjdk:8 as builder
# 执行工作目录
WORKDIR application
# 将编译构建得到的jar文件复制到镜像空间中
copy target/edevp-store-biz-0.0.1.jar application.jar
expose 8101
# 通过工具spring-boot-jarmode-layertools从application.jar中提取拆分后的构建结果
RUN java -Djarmode=layertools -jar application.jar extract
# 正式构建镜像
FROM openjdk:8
WORKDIR application
# 前一阶段从jar中提取除了多个文件,这里分别执行COPY命令复制到镜像空间中,每次COPY都是一个layer
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.JarLauncher"]

我们在项目根目录执行打包命令

mvn clean package -U -DskipTests

在这里插入图片描述

如果我们解压我们的jar就会发现多了 layers.idx 文件,打开文件我们会发现有如下内容

dependencies
spring-boot-loader
snapshot-dependencies
application

在这里插入图片描述

发布docker镜像

在这里插入图片描述

修改代码重新发布docker

在这里插入图片描述
第一次构建可能会有点慢,如果我们后续改了文件重新打包成镜像会快很多,因为有缓存,我们打包又是分了层,这种分层方式比打整个jar包的方式大概能快1倍的速度左右,具体性能差异还是要自己多测试

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

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

相关文章

Windows11安装Maven

Windows11安装Maven官网下载压缩包&#xff1a;https://maven.apache.org/download.cgi 解压到任意盘 配置环境变量 3.1 右击我的电脑&#xff0c;选择属性 3.2 选择高级系统设置 3.3 选择环境变量 3.4 在系统变量中单击新建 3.5 新建 MAVEN_HOME 变量&#xff0c;然后…

四十四、​Fluent 收敛标准-质量和能量守恒

1. Fluent质量和能量守恒 Fluent收敛性的判断有时候很让人头疼&#xff0c;我们在三十二、Fluent收敛判断标准及方法中概括的讲述过几种收敛标准。 通常我们判断是否收敛最直接的就是看残差曲线&#xff0c;但是很多时候&#xff0c;残差曲线&#xff08;尤其连续性曲线&#x…

web前端期末大作业 html+css古诗词主题网页设计

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 茶文化网站 | 中华传统文化题材 | 京剧文化水墨风书画 | 中国民间年画文化艺术网站 | 等网站的设计与制作 | HTML期末大学生网页设计作业&#xff0c;…

Linux从入门到入土③(GCC、静态与动态链接库、Git、Make、Makefile)

文章目录编译工具GCCGCC基本语法GCC编译流程预处理阶段编译阶段汇编阶段链接阶段GCC常用参数总结多文件编译静态与动态链接库Linux库的创建与使用静态库与动态库的区别静态库的制作与使用动态库的制作与使用解决动态库无法加载问题库的工作原理动态链接器解决方案静态库和动态库…

[附源码]java毕业设计日常饮食健康推荐平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【快速掌握Docker】Docker高级运用汇总--Dockerfile、Docker Compose与Docker Swarm使用

一、Dockerfile的构建 1、指定镜像 采用FROM指令&#xff1a; FROM 指定镜像名称2、设置标签信息 对镜像进行备注说明&#xff1a; LABEL manager"admin" \ label1"docker build1" \ lable2"docker build2"3、运行命令 容器运行后&#xf…

跟艾文学编程《Python基础》(6)numpy数值计算

作者&#xff1a; 艾文&#xff0c;计算机硕士学位&#xff0c;企业内训讲师和金牌面试官&#xff0c;公司资深算法专家&#xff0c;现就职BAT一线大厂。 邮箱&#xff1a; 1121025745qq.com 博客&#xff1a;https://wenjie.blog.csdn.net/ 内容&#xff1a;跟艾文学编程《Pyt…

java学习之包

包的引入 举例&#xff1a;小明和小强都想给自己定义的类命名为Dog&#xff08;在同一个文件夹下不能有同名的类&#xff09;&#xff0c;包可以解决这个问题 包的作用 1.区分相同名字的类&#xff1a;可以把Dog类放在不同的包 2.当类很多的时候&#xff0c;可以很好的管理…

人工智能在医疗保健服务演变中的作用越来越大

人工智能正被应用于医疗保健服务中&#xff0c;使用的更多技术&#xff0c;从物联网和大数据到聊天机器人。然而&#xff0c;人工智能将破坏医疗保健的主要案例&#xff0c;是计算机辅助诊断。研究综述。 医疗保健提供者和支付方都在进行数字化转型。研究显示&#xff0c;现在…

sp-踩坑小记

想把$BSGS修改为从gUserdefined继承&#xff0c;只能删掉原来的$BSGS&#xff0c;然后在gUserdefined新建一个$BSGS----坑① 如果这个BSGS里面有200个属性&#xff0c;那么还得手动再敲一遍&#xff08;无法批量导入属性&#xff09;--坑② 新建的时候&#xff0c;在虚拟机的…

计算机毕业设计ssm+vue基本微信小程序的拼车自助服务小程序

项目介绍 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱拼车自助服务小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行拼车自助服务小程序的设计与开发的数据…

关于4diac的发布/订阅和客户端/服务端功能块的思考

关于4diac的发布/订阅和客户端/服务端功能块的思考 1、PUBLISH和SUBSCRIBE功能块通信 发布/订阅功能块是多对多通信&#xff0c;采用组播的方式&#xff0c;此时的IP地址应为D类IP地址224~239&#xff0c;使用其他的ip地址&#xff0c;则SUBSCRIBE功能块接收不到 2、CLIEN…

【Java八股文总结】之JVM

文章目录JVM一、JVM内存区域1、运行时数据区域1、程序计数器2、java虚拟机栈Q&#xff1a;栈可能出现的两种错误3、本地方法栈4、堆Q&#xff1a;堆中会出现的错误Q&#xff1a;堆中对象的分配过程5、方法区Q&#xff1a;堆和栈的区别&#xff1f;2、为什么要将永久代&#xff…

STM32CubeIDE下载安装

一&#xff0c;下载安装。 官方下载地址&#xff1a; STM32CubeIDE - STM32的集成开发环境 - STMicroelectronics 下载需要注册账号&#xff0c;或者登记信息。 安装过程很简单&#xff0c;默认next就行&#xff0c;不过注意安装文件目录不要有中文&#xff0c;不然会报错&a…

java计算机毕业设计ssm美妆产品进销存管理系统

项目介绍 随着经济的发展和信息技术的普及,国内许多企业都面临了重大的挑战。企业的管理流程、战略规划如果不能进行调整,极有可能面临淘汰的风险。特别是美妆企业,面对大量的美妆产品和进销售管理,如果不使用信息系统进行有效的管理和利用,那就会阻碍企业的发展,使企业在市场…

学生dreamweaver网页设计作业成品___辅导网站( 4页 登录注册 轮播图)

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | | HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&#xff1a;结构 CSS&#xff1a;样式 在操作方面上运用了html5和css3&#xff0c; 采…

高性能 MySQL - 第六章 查询性能优化

最近阅读MySQL高性能&#xff0c;略有收获&#xff0c;好记忆不如烂笔头&#xff0c;记录一下。本期笔记主要是围绕高性能MySQL第六章查询性能优化。 整体结构 重点、亮点内容摘抄 第六章 查询性能优化 查询优化、索引优化、库表结构优化需要齐头并进&#xff0c;一个不落。在…

nodejs express 的基本使用

测试需要快速过一遍express的基本使用方法 直接安装express使用 express和koa的区别](https://zhuanlan.zhihu.com/p/372128788)egg.js企业级开发框架 npm install exress --save可以使用express-generator生成项目框架 $ npx express-generatorwarning: the default view …

call()、apply()、bind() 区别、使用场景、实现方式

目录 1. call()、apply()、bind() 三者区别 1.1 作用 1.2 参数 1.3 执行时机 2. call()、apply() 使用场景 2.1 使用 Array.prototype.push.apply(arr1, arr2) 合并两个数组 2.1.1 原理&#xff08;看了手写方法&#xff0c;或许会更有助于理解&#xff09; 2.1.2 如何…

微电网两阶段鲁棒优化(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…