SpringBoot項目docker分層鏡像構建案例
摘要:本文主要介紹Spring Boot項目的docker鏡像分層構建,分為外部依賴和內部依賴和項目classes依賴,讓docker構建的時候,可以使用之前的緩存,加快構建速度和測試環(huán)境鏡像拉取速度。
為什么使用分層 Docker 鏡像?
傳統(tǒng)的 Docker 鏡像構建方式會將整個應用程序 JAR/WAR 文件復制到一個層中。當你修改代碼時,整個層都會失效,導致 Docker 必須重新構建整個應用程序層,即使只是做了微小的代碼更改。
通過我們的分層方法,我們將以下內容分離:
- 外部依賴(第三方庫)
- 內部依賴(公司特定庫)
- 應用程序代碼(實際業(yè)務邏輯)
這樣,當你修改代碼時,只需要重新構建應用程序代碼層,而依賴層可以從緩存中重用。
Maven 插件配置詳解
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-external-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/external</outputDirectory>
<includeScope>compile</includeScope>
<excludeGroupIds>cn.hutool</excludeGroupIds>
</configuration>
</execution>
<execution>
<id>copy-internal-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/internal</outputDirectory>
<includeScope>compile</includeScope>
<includeGroupIds>cn.hutool</includeGroupIds>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
<encoding>UTF-8</encoding>
<!-- 如果使用預覽特性 -->
<compilerArgs>
<arg>--enable-preview</arg>
</compilerArgs>
<release>21</release>
</configuration>
</plugin>
</plugins>
</build>
工作原理
1. Maven 依賴分離插件配置詳解
我們的 pom.xml 使用 maven-dependency-plugin 在構建過程中分離依賴。該插件包含兩個執(zhí)行配置:
外部依賴復制配置
<execution>
<id>copy-external-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/external</outputDirectory>
<includeScope>compile</includeScope>
<excludeGroupIds>cn.hutool</excludeGroupIds>
</configuration>
</execution>
配置參數(shù)說明:
<id>: 執(zhí)行的唯一標識符
<phase>: 綁定到 Maven 生命周期的 package 階段
<goals>: 執(zhí)行的目標是 copy-dependencies
<configuration>: 配置詳情
<outputDirectory>: 輸出目錄,${project.build.directory}是 target 目錄<includeScope>: 包含作用域為 compile 的依賴<excludeGroupIds>: 排除 groupId 為 cn.hutool 的依賴(將其視為內部依賴)
內部依賴復制配置
<execution>
<id>copy-internal-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/internal</outputDirectory>
<includeScope>compile</includeScope>
<includeGroupIds>cn.hutool</includeGroupIds>
</configuration>
</execution>
配置參數(shù)說明:
<id>: 執(zhí)行的唯一標識符
<phase>: 同樣綁定到 Maven 生命周期的 package 階段
<goals>: 執(zhí)行的目標也是 copy-dependencies
<configuration>: 配置詳情
<outputDirectory>: 輸出目錄為 target/lib/internal<includeScope>: 包含作用域為 compile 的依賴<includeGroupIds>: 只包含 groupId 為 cn.hutool 的依賴(作為內部依賴處理)
通過這兩個執(zhí)行配置,Maven 會在 package 階段自動將依賴分別復制到對應的目錄中:
target/lib/external/- 第三方依賴(排除了 cn.hutool)target/lib/internal/- 內部/公司特定依賴(只有 cn.hutool)target/classes/- 編譯后的應用程序代碼
2. 分層 Dockerfile 詳解
我們的 Dockerfile 通過首先復制依賴來利用 Docker 層緩存:
FROM eclipse-temurin:21-jre-alpine WORKDIR /app # 1. 復制外部依賴(很少更改) COPY target/lib/external/*.jar ./lib/external/ # 2. 復制內部依賴(偶爾更改) COPY target/lib/internal/*.jar ./lib/internal/ # 3. 復制應用程序類(經常更改) COPY target/classes ./classes EXPOSE 8080 ENV CUSTOM_OPTS="-Xms256m -Xmx768m" ENV JAVA_OPTS="--enable-preview -XX:+UseSerialGC" ENTRYPOINT ["sh", "-c", "java $CUSTOM_OPTS $JAVA_OPTS -cp /app/classes:/app/lib/external/*:/app/lib/internal/* com.example.layer.Sp3LayerApplication"]
Dockerfile 配置說明:
FROM eclipse-temurin:21-jre-alpine: 使用輕量級的 Alpine Linux 上的 Temurin JDK 21 運行時環(huán)境
WORKDIR /app: 設置工作目錄為 /app
COPY target/lib/external/*.jar ./lib/external/: 將外部依賴復制到鏡像中,這是最穩(wěn)定的層
COPY target/lib/internal/*.jar ./lib/internal/: 將內部依賴復制到鏡像中,這層比外部依賴更可能變化
COPY target/classes ./classes: 將應用程序類文件復制到鏡像中,這層最容易發(fā)生變化
EXPOSE 8080: 暴露應用程序端口
ENV 指令設置 JVM 參數(shù):
CUSTOM_OPTS: 自定義 JVM 參數(shù),設置初始堆內存和最大堆內存JAVA_OPTS: Java 虛擬機選項,啟用預覽特性和使用串行垃圾收集器
ENTRYPOINT: 定義容器啟動時執(zhí)行的命令,使用類路徑包含所有依賴和應用程序類
類路徑說明:
-cp /app/classes:/app/lib/external/*:/app/lib/internal/* 指定了類路徑的順序:
- /app/classes: 應用程序編譯后的類文件優(yōu)先級最高
- /app/lib/external/*: 外部依賴次之
- /app/lib/internal/*: 內部依賴最后
這種順序確保了應用程序類可以覆蓋依賴中的同名類(如果需要的話),并且保證了正確的類加載順序。
3. 構建過程詳解
Maven 構建生命周期集成
當執(zhí)行 mvn package 命令時,Maven 會按照以下順序執(zhí)行構建階段:
- validate - 驗證項目正確性
- compile - 編譯源代碼
- test - 運行測試
- package - 打包應用程序
在 package 階段,maven-dependency-plugin 會自動執(zhí)行我們配置的兩個依賴復制任務:
- 首先執(zhí)行 copy-external-dependencies,將外部依賴復制到 target/lib/external/
- 然后執(zhí)行 copy-internal-dependencies,將內部依賴復制到 target/lib/internal/
- 同時,Maven 默認會將編譯后的類文件放在 target/classes/ 目錄中
完整構建步驟
清理并打包應用程序:
mvn clean package
此命令會觸發(fā)依賴分離過程,生成三個目錄:
target/classes/- 應用程序編譯后的類文件target/lib/external/- 外部依賴 JAR 文件target/lib/internal/- 內部依賴 JAR 文件
- 構建 Docker 鏡像:
docker build -t sp3-layer .
Docker 構建過程會按順序創(chuàng)建四個層:
- 基礎鏡像層(eclipse-temurin:21-jre-alpine)
- 外部依賴層(COPY target/lib/external/*.jar)
- 內部依賴層(COPY target/lib/internal/*.jar)
- 應用程序類層(COPY target/classes)
構建優(yōu)化效果
由于 Docker 的層緩存機制:
- 當只修改應用程序代碼時,只有最后一層需要重建
- 當添加新的外部依賴時,需要重建外部依賴層及其后的所有層
- 當添加新的內部依賴時,需要重建內部依賴層和應用程序類層
- 只有基礎鏡像變更時,才需要完全重建
優(yōu)勢
- 更快的構建速度:代碼更改時只需重新構建應用程序代碼層
- 更小的傳輸量:推送到注冊中心時,只傳輸更改的層
- 更好的緩存效果:依賴層在各個構建之間緩存并重用
- 減少帶寬消耗:在 CI/CD 流水線中減少數(shù)據(jù)傳輸
版本更新工作流程
- 在應用程序中進行代碼更改
- 運行
mvn clean package僅重新編譯更改的代碼 - 運行
docker build -t sp3-layer:v2 .構建新鏡像 - 只有
target/classes層會被重新構建 - 只將更改的層推送到容器注冊中心
配置自定義指南
要將此配置應用于其他項目,您需要根據(jù)項目的依賴結構調整配置:
修改依賴分組
如果您有不同的內部依賴,需要修改 excludeGroupIds 和 includeGroupIds 配置:
<!-- 外部依賴配置 --> <excludeGroupIds>com.yourcompany,org.another.internal.group</excludeGroupIds> <!-- 內部依賴配置 --> <includeGroupIds>com.yourcompany,org.another.internal.group</includeGroupIds>
最佳實踐
- 順序很重要:首先復制不經常更改的層
- 最小化層數(shù):只分離實際在不同頻率下更改的內容
- 多階段構建:考慮與多階段構建結合使用以獲得更小的最終鏡像
- 緩存失效:了解 Docker 的層緩存機制以最大化收益
這種方法可以顯著減少 CI/CD 流水線中的構建時間,并在部署更新時最小化網絡傳輸。
到此這篇關于SpringBoot項目docker分層鏡像構建案例的文章就介紹到這了,更多相關SpringBoot docker分層鏡像 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- SpringBoot程序打包Docker鏡像的最佳方式
- SpringBoot Docker鏡像分層的優(yōu)化指南
- SpringBoot制作Docker鏡像接入SkyWalking的詳細過程
- Docker自定義鏡像的實現(xiàn)步驟(SpringBoot程序為例)
- Docker打包SpringBoot鏡像的實現(xiàn)方式
- SpringBoot打包成Docker鏡像的項目實踐
- SpringBoot打包成Docker鏡像的幾種實現(xiàn)方式
- 一步步教你把SpringBoot項目打包成Docker鏡像
- SpringBoot打包docker鏡像發(fā)布的詳細步驟
- SpringBoot構建Docker鏡像的實現(xiàn)步驟
相關文章
基于params、@PathVariabl和@RequestParam的用法與區(qū)別說明
這篇文章主要介紹了方法參數(shù)相關屬性params、@PathVariabl和@RequestParam用法與區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08
IntelliJ IDEA cmd和idea Terminal查看java版本不一致的解決
原來win10電腦上安裝的是jdk8的版本,因某些原因,現(xiàn)在想換成jdk7的版本,修改環(huán)境變量后,在cmd中執(zhí)行 [java -version]命令,顯示的是7的版本,遇到這樣的問題如何解決呢?下面小編給大家分享IntelliJ IDEA cmd和idea Terminal查看java版本不一致的解決方案,一起看看吧2023-09-09
springboot如何獲取yaml/yml(或properties)配置文件信息
在SpringBoot項目中,讀取配置文件信息是常見需求,可以通過@Autowired注入Environment類,使用@Value注解直接注入配置信息,或定義工具類結合ApplicationRunner進行高級配置信息獲取,特別提到2024-11-11
VSCode?配置?Spring?Boot?項目開發(fā)環(huán)境的全過程
兩三年前曾經試過配置Java環(huán)境, 存在不少問題作罷. 最近搜了下相關的文章, 感覺VSCode對Java項目的支持比三年前完善了不少. 今天實際配置了一下環(huán)境, 把自己常用的功能過了一遍, 基本能跑通開發(fā)流程, 做個筆記,需要的朋友可以參考下2024-03-03
java實現(xiàn)新浪微博Oauth接口發(fā)送圖片和文字的方法
這篇文章主要介紹了java實現(xiàn)新浪微博Oauth接口發(fā)送圖片和文字的方法,涉及java調用新浪微博Oauth接口的使用技巧,具有一定參考接借鑒價值,需要的朋友可以參考下2015-07-07

