小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)

1. 准备 spring boot 项目

简单,略过

spring boot 版本 > 2.3.x 即可

简单写了一个 hello world

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-猿站网-插图

2. 进行相关配置

这里网上很多 blog 都强调了要去 pom.xml 里手动配置启用分层打包:

<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!–开启分层编译支持–> <layers> <enabled>true</enabled> </layers> </configuration> </plugin> </plugins> </build>

2.3.x版本的时候因为是新功能需要手动配置开启。但是目前 spring boot 版本(使用版本2.6.1)实测不需要手动配置,默认支持该特性。(根据一些 blog 的说法是 2.4.x 版本之后就默认开启了)

目前的官方文档(2.6.0版本)的说法也是默认支持,反而不需要该特性时才需要手动配置:

The repackaged archive includes the layers.idx file by default. To disable this feature, you can do so in the following manner:

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

3. package

执行 mvn package 进行打包,得到 jar 包文件。

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-1猿站网-插图

其实实际上本质是使用了 spring-boot-maven 插件的 repackage,得到了完整的包含依赖的 jar 包和原始的 jar 包(自动添加后缀 .original)

打开 jar 包,会发现在 BOOT-INF 文件夹下有 classpath.idx 和 layers.idx 文件,打开看下:

classpath.idx

– “BOOT-INF/lib/logback-classic-1.2.7.jar”

– “BOOT-INF/lib/logback-core-1.2.7.jar”

– “BOOT-INF/lib/log4j-to-slf4j-2.14.1.jar”

– “BOOT-INF/lib/log4j-api-2.14.1.jar”

– “BOOT-INF/lib/jul-to-slf4j-1.7.32.jar”

– “BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar”

– “BOOT-INF/lib/snakeyaml-1.29.jar”

– “BOOT-INF/lib/jackson-databind-2.13.0.jar”

– “BOOT-INF/lib/jackson-annotations-2.13.0.jar”

– “BOOT-INF/lib/jackson-core-2.13.0.jar”

– “BOOT-INF/lib/jackson-datatype-jdk8-2.13.0.jar”

– “BOOT-INF/lib/jackson-datatype-jsr310-2.13.0.jar”

– “BOOT-INF/lib/jackson-module-parameter-names-2.13.0.jar”

– “BOOT-INF/lib/tomcat-embed-core-9.0.55.jar”

– “BOOT-INF/lib/tomcat-embed-el-9.0.55.jar”

– “BOOT-INF/lib/tomcat-embed-websocket-9.0.55.jar”

– “BOOT-INF/lib/spring-web-5.3.13.jar”

– “BOOT-INF/lib/spring-beans-5.3.13.jar”

– “BOOT-INF/lib/spring-webmvc-5.3.13.jar”

– “BOOT-INF/lib/spring-aop-5.3.13.jar”

– “BOOT-INF/lib/spring-context-5.3.13.jar”

– “BOOT-INF/lib/spring-expression-5.3.13.jar”

– “BOOT-INF/lib/spring-boot-2.6.1.jar”

– “BOOT-INF/lib/spring-boot-autoconfigure-2.6.1.jar”

– “BOOT-INF/lib/slf4j-api-1.7.32.jar”

– “BOOT-INF/lib/spring-core-5.3.13.jar”

– “BOOT-INF/lib/spring-jcl-5.3.13.jar”

– “BOOT-INF/lib/spring-boot-jarmode-layertools-2.6.1.jar”

layers.idx

– “dependencies”:

  – “BOOT-INF/lib/”

– “spring-boot-loader”:

  – “org/”

– “snapshot-dependencies”:

– “application”:

  – “BOOT-INF/classes/”

  – “BOOT-INF/classpath.idx”

  – “BOOT-INF/layers.idx”

  – “META-INF/”

再验证一下:

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-2猿站网-插图

分层信息 ok

4. Dockerfile

Dockerfile 文件也相对常规,只是在打包镜像之前使用 jarmode 命令把 jar 包解压了,然后在打包镜像过程中将不同层依次 COPY,将改动可能性最大的应用层放在最后,这样前面的没有变化就可以直接使用 Docker 的缓存以提高打包效率。

FROM eclipse-temurin:8-jre-focal 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:8-jre-focal  

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/ ./  

ENV TZ=”Asia/Shanghai”  

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone  

ENV JVM_OPTS=””  

ENV JAVA_OPTS=””  

ENTRYPOINT [“sh”,”-c”,”java $JVM_OPTS $JAVA_OPTS org.springframework.boot.loader.JarLauncher”]

5. 应用程序修改&dive分析

其实如果只打包一次镜像是没有体现分层的优势的,所以需要修改部分内容后再打包一次(或者多次,但是本质是一样的所以这里只修改了一次)

修改部分应用代码:

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-3猿站网-插图

重新打 jar 包&重新打镜像,这样得到了两个镜像:

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-4猿站网-插图

使用 dive 对两个镜像进行分析:

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-5猿站网-插图

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-6猿站网-插图

%小知识:Spring Boot 分层打包 Docker 镜像实践及分析(推荐)-7猿站网-插图

可以发现:直到发生改变的应用层(application/application/)之前,两边的分层的 Id、Digest 都是完全一致的,所以这些层是可以复用的,相同的层只会在 docker 的目录下存储单个,如此可以大大减少容器编译、推送的时长。

(具体 docker 镜像的分层的了解还有限,后续再进一步了解)

到此这篇关于Spring Boot 分层打包 Docker 镜像实践及分析的文章就介绍到这了,更多相关Spring Boot 分层打包 Docker 镜像内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/cbc-onne/archive/2021/12/09/15669577.html

声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:docker容器时区错误问题

2023-3-12 15:58:49

建站知识

小知识:Docker容器编译LNMP的实现示例

2023-3-12 16:13:32

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索