Spring Boot分层打包码头工人镜像实践及分析
Spring Boot 分层打包 Docker 镜像实践及分析
1. 准备 spring boot 项目
简单,略过
板簧罩版本2.3.x即可
简单写了一个你好世界
2. 进行相关配置
这里网上很多博客都强调了要去pom.xml里手动配置启用分层打包:
建设
插件
插件
groupIdorg.springframework.boot/groupId
artifactIdspring-boot-maven-plugin/artifactId
配置
!-开启分层编译支持-
层
enabledtrue/enabled
/layers
/配置
/插件
/plugins
/build
2.3.x版本的时候因为是新功能需要手动配置开启。但是目前 spring boot 版本(使用版本2.6.1)实测不需要手动配置,默认支持该特性。(根据一些博客的说法是2.4.x版本之后就默认开启了)
目前的官方文档(2.6.0版本)的说法也是默认支持,反而不需要该特性时才需要手动配置:
默认情况下,重新打包的归档包括layers.idx文件。要禁用此功能,您可以通过以下方式进行操作:
项目
建设
插件
插件
groupIdorg.springframework.boot/groupId
artifactIdspring-boot-maven-plugin/artifactId
配置
层
enabledfalse/enabled
/layers
/配置
/插件
/plugins
/build
/project
3. package
执行mvn包进行打包,得到冲突包文件。
其实实际上本质是使用了弹簧靴专家插件的重新包装,得到了完整的包含依赖的冲突包和原始的冲突包(自动添加后缀。原文)
打开冲突包,会发现在BOOT-INF文件夹下有classpath.idx和layers.idx文件,打开看下:
classpath.idx
-“BOOT-INF/lib/log back-classic-1。2 .7 .罐子"
-“BOOT-INF/lib/log back-core-1。2 .7 .罐子"
-“BOOT-INF/lib/log4j-to-slf4j-2。14 .1 .罐子"
-“BOOT-INF/lib/log4j-API-2。14 .1 .罐子"
-" BOOT-INF/lib/jul-to-slf4j-1。7 .32 .罐子"
-" BOOT-INF/lib/雅加达。注释-API-1。3 .5 .罐子"
-BOOT-INF/lib/seriayaml-1.29。罐子
-“BOOT-INF/lib/Jackson-数据绑定-2。13 .0 .罐子"
-BOOT-INF/lib/Jackson-annotations-2。13 .0 .罐子
-BOOT-INF/lib/Jackson-core-2。13 .0 .罐子
-BOOT-INF/lib/Jackson-datatype-JDK 8-2。13 .0 .罐子
-BOOT-INF/lib/Jackson-datatype-JSR 310-2。13 .0 .罐子
-BOOT-INF/lib/Jackson-module-parameter-name-2。13 .0 .罐子
-BOOT-INF/lib/Tomcat-embed-core-9。0 .55 .罐子
-BOOT-INF/lib/Tomcat-embed-El-9。0 .55 .罐子
-BOOT-INF/lib/Tomcat-embed-web socket-9。0 .55 .罐子
-BOOT-INF/lib/spring-web-5。3 .13 .罐子
-BOOT-INF/lib/spring-beans-5。3 .13 .罐子
-BOOT-INF/lib/spring-web MVC-5。3 .13 .罐子
-BOOT-INF/lib/spring-AOP-5。3 .13 .罐子
-BOOT-INF/lib/spring-context-5。3 .13 .罐子
-BOOT-INF/lib/spring-expression-5。3 .13 .罐子
-“BOOT-INF/lib/spring-BOOT-2。6 .1 .罐子"
-BOOT-INF/lib/spring-BOOT-auto configure-2。6 .1 .罐子
-“BOOT-INF/lib/slf4j-API-1。7 .32 .罐子"
-BOOT-INF/lib/spring-core-5。3 .13 .罐子
-BOOT-INF/lib/spring-JCL-5。3 .13 .罐子
-BOOT-INF/lib/spring-BOOT-jar模式-层工具-2。6 .1 .罐子
layers.idx
-"依赖关系":
- 'BOOT-INF/lib/'
-"弹簧-启动加载器":
-"组织/"
-"快照-相关性":
-"应用程序":
-' BOOT-INF/class/'
- 'BOOT-INF/classpath.idx '
- 'BOOT-INF/layers.idx '
- 'META-INF/'
再验证一下:
分层信息好的
4. Dockerfile
文件文件也相对常规,只是在打包镜像之前使用jarmode命令把冲突包解压了,然后在打包镜像过程中将不同层依次COPY,将改动可能性最大的应用层放在最后,这样前面的没有变化就可以直接使用码头工人的缓存以提高打包效率。
来自eclipse-temurin :8-JRE-focal as builder
工作目录应用程序
ARG JAR_FILE=target/* .冲突
COPY ${JAR_FILE}应用程序。冲突
RUN Java-Djarmode=层工具-jar应用。罐子提取物
发自日蚀-天目:8-JRE-焦点
工作目录应用程序
复制自=构建器应用程序/依赖项/。/
复制自=构建器应用程序/spring-boot-loader/./
COPY-from=构建器应用程序/快照-依赖项/。/
COPY - from=builder应用程序/application/。/
TZ=亚洲/上海
运行ln-SNF/usr/share/zoneinfo/$ TZ/etc/local time echo $ TZ/etc/时区
ENV JVM_OPTS=' '
' ENV JAVA_OPTS=' '
ENTRYPOINT ['sh ','-c ',' JAVA $ JVM _ OPTS $ JAVA _ OPTS org . spring framework . boot . loader . JarLauncher ']
5. 应用程序修改dive分析
其实镜像如果只打包一次,并不能体现出分层的优势,所以需要修改一些内容后再打包(或者打包几次,但本质是一样的,所以这里只修改一次)。
修改一些应用程序代码:
重新播放jar包并重新镜像,因此您将获得两个镜像:
使用dive分析两个镜像:
可以发现,直到改变的应用层(application/application/)之前,两层的Id和Digest都是完全一致的,所以这些层是可以重用的,同一层只有一层会存储在docker目录中,可以大大减少编译和推送容器的时间。
(对具体码头工人形象的层次感理解还是有限,后面会详细了解)
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/141452.html