Spring Boot 2.3 中分层jar 是什么东西
背景
在我们实际生产容器化部署过程中,往往会遇到 Docker 镜像很大,部署发布很慢的情况
影响 docker 镜像大小的因素,主要有以下三个方面:
-
- 基础镜像的大小 。尽量选择 aphine 作为基础镜像 减少操作系统内置软件
-
- Dockerfile 指令层数。 这就要求我们优化 Dockerfile 能合并在一行的尽量合并等
-
- 应用 jar 的大小。这是今天要分享的重点内容
helloworld 镜像
我们先来基于 spring boot 2.3.0
构建一个最简单的 web helloworld,然后构建镜像。
FROM adoptopenjdk:11-jre-hotspot as builder WORKDIR application ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} application.jar ENTRYPOINT ["java", "-jar application.jar"]
docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar . -t demo:v1.0
查看镜像分层信息
我们通过 docker inspect demo:v1.0
来看下此镜像的每层的散列值
// demo:v1.0 版本镜像分层信息摘要 "Layers": [ "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e", "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6", "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794", "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233", "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab", "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d", "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535", "sha256:b87d2ff74819f83038ea2f89736a19cfcf99bfa080b8017d191c900a09a7524f" ]
helloworld 升级重新构建
我们对 helloworld
程序进行部分修改(模拟开发过程),然后重新构建镜像
docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar . -t demo:v1.1
此时镜像分层信息如下 docker inspect demo:v1.1
// demo:v1.1 版本镜像分层信息摘要 "Layers": [ "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e", "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6", "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794", "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233", "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab", "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d", "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535", "sha256:c1b6350d545fea605e0605c4bfd7f4529cfeee3f6759750d6a5ddeb9c882fc8f" ]
比较 v1.0、v1.1 镜像
通过比较 v1.0 和 v1.1 版本的镜像摘要信息,我们会发现只有最后的一层发生了变化,我们通过 Dive 是一个用 Go 语言编写的 Docker 镜像分析工具 来确定一下 最后一层是做了哪些事情
dive demo:v1.0
,大家会看到是最后的 jar 不一样 导致 16M 的内容需要重新构建,当你的业务 jar 很大时,这块就是性能瓶颈
spring boot 默认打包解密
默认情况下,spring boot 构建出来的 jar ,解压后可以看到如下目录结构。默认会当做一个整体 ,在构建镜像时作为一个单独层,没有区分业务 classes 和 引用的第三方 jar
META-INF/ MANIFEST.MF org/ springframework/ boot/ loader/ BOOT-INF/ classes/ lib/
layer jar
通过上文大家就可以知道分层 jar 的思想就是把,jar 再根据规则细分,业务 class 和 三方 jar 分别对应镜像的不同层,这样改动业务代码,只需变动很少的内容 提高构建速度。
开启分层打包
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layers> <enabled>true</enabled> </layers> </configuration> </plugin>
编写支持分层 Dockerfile
核心是通过 spring boot 提供的 layertools
工具,将 jar 进行拆分 然后通过 COPY 指令去分别加载
FROM adoptopenjdk:11-jre-hotspot as builder WORKDIR application ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} application.jar RUN java -Djarmode=layertools -jar application.jar extract FROM adoptopenjdk:11-jre-hotspot 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.JarLauncher"]
构建新镜像并查看分层信息
docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar . -t demo:v2.0
"Layers": [ "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e", "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6", "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794", "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233", "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab", "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d", "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535", "sha256:06fe18cf8ae7384f120f2c6a3a33b31999dd0460cf1edae45e8f13adeab35942", "sha256:16cf814564b8a667fcc9f07314b6084cbef8dc8c0a6565c7a2d91d74faf7e7de", "sha256:94be40f716016b68cdd6b99d2cb8154acf8475c3a170a898a22f95a8ef40ffd3", "sha256:427d87d6a5fe6da13cb4233939c3a1ff920bc6b4d2f14b5d78af7aef98fda7de" ]
修改代码部分业务代码,重新构建
docker build --build-arg JAR_FILE=./demo-layer-0.0.1-SNAPSHOT.jar . -t demo:v2.1
"Layers": [ "sha256:b7f7d2967507ba709dbd1dd0426a5b0cdbe1ff936c131f8958c8d0f910eea19e", "sha256:a6ebef4a95c345c844c2bf43ffda8e36dd6e053887dd6e283ad616dcc2376be6", "sha256:838a37a24627f72df512926fc846dd97c93781cf145690516e23335cc0c27794", "sha256:28ba7458d04b8551ff45d2e17dc2abb768bf6ed1a46bb262f26a24d21d8d7233", "sha256:55c91231ac46fdd63c3cf84b88b11f8a04c1870482dcff033029a601bc50e1ab", "sha256:9816c2d488754509f6024a267738b1e5fe33a7cd33bd25c5a9cdf6d4d7bfed1d", "sha256:f5fb3f91797d57a92f3f7e033398b8edd094df664db849a4950eabf2f5474535", "sha256:06fe18cf8ae7384f120f2c6a3a33b31999dd0460cf1edae45e8f13adeab35942", "sha256:16cf814564b8a667fcc9f07314b6084cbef8dc8c0a6565c7a2d91d74faf7e7de", "sha256:94be40f716016b68cdd6b99d2cb8154acf8475c3a170a898a22f95a8ef40ffd3", "sha256:8a20c60d361696a4e480fb6fbe1daf8b88bc54c579a98e209da1fb76e25de5aa" ]
查看区别层镜像
最后一层变动大小为 5KB
总结
- 16MB -> 5KB 变动,在实际开发过程中 效果会更加明显
- 可以通过 spring boot maven plugin 指定分层逻辑,具体可以参考官方文档
- 官方文档: https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/maven-plugin/reference/html
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java 泛型背后的原理是什么?
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 这一节主要讲的内容是java中泛型的应用,通过该篇让大家更好地理解泛型,以及面试中经常说的泛型类型擦除是什么概念,今天就带着这几个问题一起看下:举一个简单的例子: 这里可以看出来在代码编写阶段就已经报错了,不能往string类型的集合中添加int类型的数据。那可不可以往List集合中添加多个类型的数据呢,答案是可以的,其实我们可以把list集合当成普通的类也是没问题的,那么就有下面的代码: 从这里可以看出来,不定义泛型也是可以往集合中添加数据的,所以说泛型只是一种类型的规范,在代码编写阶段起一种限制。下面我们通过例子来介绍泛型背后数据是什么类型 public class BaseBean<T> { T value; public T getValue() { return value; } public void setValue(T value) { this.value = value; } } 上面定义了一个泛型的类,然后我们通过反射获取属性和getValue方法返回的...
- 下一篇
安防视频监控行业的“新基建”要如何落地?
“两会”期间, “新基建”(即新型基础设施建设)被频频提及,并且被首次写入《政府工作报告》,国家提出了对 "新基建" 的 2020 计划 ,具体指: 加强新型基础设施建设,发展新一代信息网络,拓展 5G 应用,建设充电桩,推广新能源汽车,激发新消费需求、助力产业升级。 作为“新基建”的重要内容,具有高速率、低时延、大带宽等特点的5G网络将迈入快速发展的新阶段。而随着5G网络的发展,一些相关行业也将随之出现变革。以视频监控行业为例: 首先,超高清视频时代到来 不断变化的市场需求使得视频图像逐步从标清、走向高清甚至超高清。5G网络技术的普及还将推进超高清视频的传输效率进一步提升,从而解决数据提取及进行分析应用时,因为图像的清晰度不够而无法使用的问题。 其次,智能化成为发展趋势。 人脸识别、行为识别、车牌识别、目标分类等人工智能算法的快速发展,使得安防智能化成为了近两年最为明显的一个发展趋势。 根据IDC的相关预测, AI摄像头将持续高速增长,并大量替换传统摄像头。智能视频监控技术近几年来被广泛研究并开始实际应用,通过将AI相关的视觉技术融入视频监控系统,可以对视频数据流进行图像处理、目标分...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8编译安装MySQL8.0.19