原创 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
原创 Spring Boot 2.3 新特性分层JAR的更多相关文章
- Spring Boot 2(一):Spring Boot 2.0新特性
Spring Boot 2(一):Spring Boot 2.0新特性 Spring Boot依赖于Spring,而Spring Cloud又依赖于Spring Boot,因此Spring Boot2 ...
- Spring Boot 2.0 新特性和发展方向
以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...
- 【2.0新特性】Spring Boot 2.0新特性
以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...
- Spring Boot实践——Spring Boot 2.0 新特性和发展方向
出自:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Jav ...
- Spring Boot 2.0 新特性
这是一篇总结文章,主要收集 Spring Boot 2.0 相对于 Spring Boot 1.x 的新特性,本章节并不提供实践性质的源代码.在 Spring Boot 系列文章中会持续退出实践章节. ...
- 「Spring Boot 2.4 新特性」一键构建Docker镜像
背景 在我们开发过程中为了支持 Docker 容器化,一般使用 Maven 编译打包然后生成镜像,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很方便.docker-maven-plugi ...
- Spring Boot 2.3 新特性优雅停机详解
什么是优雅停机 先来一段简单的代码,如下: @RestController public class DemoController { @GetMapping("/demo") p ...
- 『Spring Boot 2.4新特性』减少95%内存占用
节省 95%的内存占用,减少 80%的启动耗时. GraalVM 是一种高性能的虚拟机,它可以显著的提高程序的性能和运行效率,非常适合微服务.最近比较火的 Java 框架 Quarkus 默认支持 G ...
- 「Spring Boot 2.4 新特性」启动耗时详细监控
背景 Spring Boot 项目随着项目开发过程中引入中间件数量的增加,启动耗时 逐渐增加. 笔者在 <Spring Boot 2.4.0 正式 GA,全面拥抱云原生>文章评论下发现了 ...
随机推荐
- app启动速度怎么提升?
简介: APP 启动速度的重要性不言而喻.高德地图是一个有着上亿用户的超级 APP,本文从唤端技术.H5 启动页.下载速度.APP加载.线程调度和任务编排等方面,详解相关技术原理和实现方案,分享高德在 ...
- 精密进近OCH的计算
一.计算步骤 以I类精密进近为例,运行标准的制定大致分为以下几个步骤: 1)确定精密航段的超高障碍物. 2)计算当量高 3)计算高度损失 4)当量高与高度损失相加得到超障高OCH 5)对复飞段障碍物进 ...
- mysql数据库表引入redis解决方案
缓存方案 缓存方案在我的另外一篇博客里有详细说明,地址:https://www.cnblogs.com/wingfirefly/p/14419728.html 数据结构: 方案1: 1.存储结构采用h ...
- 解决margin-top无效问题
当两个空的块级元素嵌套时,如果内部的块设置有margin-top属性,而且父元素没有下边解决方法所述的特征,那么内部块的margin-top属性会绑架父元素(即将margin-top传递凌驾给了父元素 ...
- DOM及相关操作
1.背景介绍 什么是DOM?简单地说,DOM是一套对文档的内容进行抽象和概念化的方法, 在现实世界里,人们对所谓的'世界对象模型'都不会陌生,例如,当用'汽车'.'房子'和'树'等名词来 ...
- docker仓库之harbor高可用 (三)
基于上一篇部署完成了企业级仓库harbor的部署,今天我们来聊聊什么是harbor的高可用 Harbor 支持基于策略的 Docker 镜像复制功能,这类似于 MySQL 的主从同步,其可以实现不同的 ...
- POJ-1062(原始dijiksra算法+思维)
昂贵的婚礼 POJ-1062 这道题目一开始看的时候难以理解,但是仔细想,还是可以和最短路联系的,我觉得类似于硬币交换等问题. 以下需要注意几个点,第一就是因为题目规定如何和超出了等级限制的人交易,则 ...
- 面试常备,字符串三剑客 String、StringBuffer、StringBuilder
尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...
- WEB服务-Nginx之十-keepalived
WEB服务-Nginx之10-keepalived 目录 WEB服务-Nginx之10-keepalived Keepalived和高可用 基本概述 Keepalived安装配置 Keepalived ...
- wireshark如何抓取分析https的加密报文
[问题概述] https流量基于ssl/tls加密,无法直接对报文进行分析. [解决方案] 方案1 -- 利用"中间人攻击"的代理方式抓包分析.整个方案过程比较简单,这里不赘述,大 ...