網站首頁 編程語言 正文
1. 準備 spring boot 項目
簡單,略過
spring boot 版本 > 2.3.x 即可
簡單寫了一個 hello world
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-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/"
再驗證一下:
分層信息 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分析
其實如果只打包一次鏡像是沒有體現分層的優勢的,所以需要修改部分內容后再打包一次(或者多次,但是本質是一樣的所以這里只修改了一次)
修改部分應用代碼:
重新打 jar 包&重新打鏡像,這樣得到了兩個鏡像:
使用 dive 對兩個鏡像進行分析:
可以發現:直到發生改變的應用層(application/application/)之前,兩邊的分層的 Id、Digest 都是完全一致的,所以這些層是可以復用的,相同的層只會在 docker 的目錄下存儲單個,如此可以大大減少容器編譯、推送的時長。
(具體 docker 鏡像的分層的了解還有限,后續再進一步了解)
原文鏈接:https://www.cnblogs.com/cbc-onne/archive/2021/12/09/15669577.html
相關推薦
- 2022-05-27 C++左值與右值,右值引用,移動語義與完美轉發詳解_C 語言
- 2022-09-20 Python?Flask中Cookie和Session區別詳解_python
- 2022-06-22 Git配置用戶簽名方式的拓展示例實現全面講解_其它綜合
- 2022-10-14 Sklearn中的二分類模型可以進行多分類的原理
- 2023-02-15 刪除docker中沒有被使用的數據卷volume_docker
- 2022-08-07 Android?無障礙服務?performAction?調用過程分析_Android
- 2022-07-18 Linux文件系統和日志分析
- 2022-06-14 golang?channel管道使用示例解析_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支