spring boot 分層構建鏡像

1、概述

spring boot 2.3 開始spring-boot-maven-plugin 插件默認開啓了分層構建 jar包 或者 war包,本文主要根據官方文檔記錄一下如何使用分層jar構建鏡像。html

2、spring-boot-maven-plugin 分層構建 jar 包

配置 spring boot 項目繼承自 spring-boot-starter-parent,設置 <parent> 以下:java

<!-- Inherit defaults from Spring Boot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.1</version>
</parent>

繼承自 spring-boot-starter-parent 的項目有以下的默認配置:spring

  • 默認編譯jdk:JDK 1.8
  • 默認編碼:UTF-8
  • 默認依賴項管理部分繼承自 spring-boot-dependencies POM,管理公共依賴項的版本,這種依賴管理容許您在本身的 POM 中使用時省略那些依賴項的<version>標記
  • 默認配置的 excution goal爲:repackage

當在項目中引入 spring-boot-maven-plugin 插件默認就開啓了分層構建 jar包,咱們可使用以下方式進行驗證:docker

  • 在項目的 pom.xml 文件中添加以下插件配置:shell

    <project>
      <modelVersion>4.0.0</modelVersion>
      <artifactId>getting-started</artifactId>
      <!-- ... -->
      <build>
          <plugins>
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
          </plugins>
      </build>
    </project>
  • 執行以下命令進行打包:緩存

    mvn clean package

    在 target 目錄下面生成對應的 jar 包,解壓 jar 包目錄結構以下:app

image.png

jar 分別在 BOOT-INF/classesBOOT-INF/lib 中包含應用程序的類和依賴項。 相似地,可執行 war 包含 WEB-INF/classes 中的應用程序類和 WEB-INF/lib WEB-INF/lib-provided 中的依賴項。 對於須要從 jar 或 war 的內容構建 docker 鏡像的狀況,須要分離這些目錄以便將它們寫入不一樣的層。maven

其中的 BOOT-INF/layers.idx 文件就是用來定義分層 jar 的構建順序的,層的順序很重要,由於它決定了在應用程序的一部分發生更改時,儘量將發生更改的內容放在後面,應該先添加最不可能更改的內容,而後再添加最可能更改的層,默認順序是:ide

  • dependencies(用於存放不包含 snapshot 的依賴)
  • spring-boot-loader(用於存放類加載器)
  • snapshot-dependencies(用於存放包含 snapshot 的依賴)
  • application(用於存放應用程序的類和資源)

image.png

此分層旨在根據應用程序構建之間更改的可能性來分離代碼,項目的依賴不太可能在內部版本之間常常更改,所以將其放置在單獨的層dependencies中,以容許工具從新使用緩存中的層,應用程序代碼更可能在內部版本之間進行更改,所以將其隔離在單獨的層application中。spring-boot

使用下面的命令查看分層jar 的目錄順序:

java -Djarmode=layertools -jar probedemo-0.0.1-SNAPSHOT.jar list

dependencies
spring-boot-loader
snapshot-dependencies
application

使用下面的命令將jar包按照分層的目錄結構進行解壓以便建立分層鏡像:

java -Djarmode=layertools -jar probedemo-0.0.1-SNAPSHOT.jar extract

關於 java -Djarmode=layertools -jar application.jar 官方的說明以下:

Usage:
  java -Djarmode=layertools -jar probedemo-0.0.1-SNAPSHOT.jar

Available commands:
  list     List layers from the jar that can be extracted
  extract  Extracts layers from the jar for image creation
  help     Help about any command

要禁用此特性,能夠採用如下方式

<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、多階段構建 docker 鏡像

知道了上面分層 jar 包的構建目錄以後,咱們可使用多階段來構建 docker 鏡像,Dockerfile 的內容以下:

# 指定基礎鏡像,這是多階段構建的前期階段
FROM openjdk:11-jre-slim as builder
# 指定工做目錄,目錄不存在會自動建立
WORKDIR /app
# 將生成的 jar 複製到容器鏡像中
COPY target/*.jar application.jar
# 經過工具spring-boot-jarmode-layertools從application.jar中提取拆分後的構建結果
RUN java -Djarmode=layertools -jar application.jar extract

# 正式構建鏡像
FROM openjdk:11-jre-slim
# 指定工做目錄,目錄不存在會自動建立
WORKDIR /app
# 前一階段從jar中提取除了多個文件,這裏分別執行COPY命令複製到鏡像空間中,每次COPY都是一個layer
COPY --from=builder app/dependencies ./
COPY --from=builder app/spring-boot-loader ./
COPY --from=builder app/snapshot-dependencies ./
COPY --from=builder app/application ./
# 指定時區
ENV TZ="Asia/Shanghai"
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 定義一些環境變量,方便環境變量傳參
ENV JVM_OPTS=""
ENV JAVA_OPTS=""
# 指定暴露的端口,起到說明的做用,不指定也會暴露對應端口
EXPOSE 8080
# 啓動 jar 的命令
ENTRYPOINT ["sh","-c","java $JVM_OPTS $JAVA_OPTS org.springframework.boot.loader.JarLauncher"]

使用下面的命令構建 docker 鏡像:

docker build -t demo:1.0.0 .

使用以下命令查看鏡像的分層信息:

docker history demo:1.0.0

image.png

如上圖,整個 jar 的內容,例如 class、依賴庫、依賴資源等,分屢次 COPY 到鏡像空間中,因此之後若是隻改了class,在更新鏡像的時候,只須要下載 class 的 layer 便可(其餘 layer 能夠直接用以前緩存到本地的)。

image.png

參考文章:

https://docs.spring.io/spring...

https://blog.csdn.net/boling_...

相關文章
相關標籤/搜索