Spring Boot 分層構建容器鏡像官方文檔學習筆記


稍微查了下發現分層構建容器鏡像是從 2.3.x 就支持了,以“spring boot 分層 構建”為關鍵詞也能找到不少中文資料,但還是先從官方文檔看起吧(雖然英語渣看得真的很痛苦)
不用指望翻譯的質量了,基本是機翻+簡(負)單(面)潤色,翻譯一遍確保我看英文的時候不會因為看不懂就下意識跳過一些東西導致整篇看下來其實啥也沒看。
並且由於整篇東西是 notion 直接復制過來的,所以格式可能也有點問題。我會粗略修正一遍但也可能有所遺漏。
言歸正傳了:

官方文檔

Spring Boot applications can be containerized using Dockerfiles, or by using Cloud Native Buildpacks to create optimized docker compatible container images that you can run anywhere.

Spring Boot 的應用能夠使用 Dockfiles 容器化,或者通過使用雲原生 BuildPacks 來創建可以在任何地方運行的優化過的 docker 兼容容器鏡像。

1. Efficient container images
It is easily possible to package a Spring Boot fat jar as a docker image. However, there are various downsides to copying and running the fat jar as is in the docker image. There’s always a certain amount of overhead when running a fat jar without unpacking it, and in a containerized environment this can be noticeable. The other issue is that putting your application’s code and all its dependencies in one layer in the Docker image is sub-optimal. Since you probably recompile your code more often than you upgrade the version of Spring Boot you use, it’s often better to separate things a bit more. If you put jar files in the layer before your application classes, Docker often only needs to change the very bottom layer and can pick others up from its cache.

  1. 高效的容器鏡像
    把一個臃腫的 Spring Boot jar 包打包成一個 docker 鏡像是很簡單的。然而,復制以及運行這種包含臃腫 jar 包的鏡像有着非常多的缺點。運行一個沒有解壓過的臃腫 jar 包總會有一定量的開銷,並且在一個容器化的環境中這將非常明顯。另一個問題是將您的應用的代碼和它全部的依賴放在 Docker 鏡像的同一層中並不是最優的。一般來說您重新編譯代碼的頻率會比您升級所用的 Spring Boot 的版本的頻率要高,因此通常情況下,把相關事物分離會比較好。如果您將 jar 文件放在您的應用程序類之前的層中,Docker 通常只需要更改最底層並且可以從它的緩存中獲取其他內容。

1.1. Unpacking the fat jar
If you are running your application from a container, you can use an executable jar, but it is also often an advantage to explode it and run it in a different way. Certain PaaS implementations may also choose to unpack archives before they run. For example, Cloud Foundry operates this way. One way to run an unpacked archive is by starting the appropriate launcher, as follows:

1.1. 解壓臃腫 jar 包
如果你要從一個容器中運行你的應用程序,可以使用一個可執行的 jar 包,但是將其分解並用一種不同的方式運行它通常也是一種優勢。某些 Paas 實現可能也會選擇在運行之前解壓歸檔文件。比如,Cloud Foundry 就是這么做的。運行未打包的歸檔文件的一種方式是啟動適當的啟動程序,如下所示:

jar -xf myapp.jar
java org.springframework.boot.loader.JarLauncher

This is actually slightly faster on startup (depending on the size of the jar) than running from an unexploded archive. At runtime you should not expect any differences.

這樣實際上在啟動時比從未分解的歸檔文件運行要稍快(取決於 jar 的大小)。但在運行時,您不應當期待能發現什么不同。

Once you have unpacked the jar file, you can also get an extra boost to startup time by running the app with its "natural" main method instead of the JarLauncher. For example:

一旦您有了解壓過的 jar 包文件,你可以通過應用程序的 “natural” 主方法而不是 JarLauncher 來運行應用來進一步縮短啟動時間。如下所示:

jar -xf myapp.jar
java -cp BOOT-INF/classes:BOOT-INF/lib/* com.example.MyApplication

Note
Using the JarLauncher over the application’s main method has the added benefit of a predictable classpath order. The jar contains a classpath.idx file which is used by the JarLauncher when constructing the classpath.

在應用程序的主方法上使用 JarLauncher 有一個額外的好處:類路徑的順序是可預測的。jar 包包含一個 classpath.idx 文件,當 JarLauncher 構造類路徑時會使用該文件。

1.2. Layering Docker Images
To make it easier to create optimized Docker images, Spring Boot supports adding a layer index file to the jar. It provides a list of layers and the parts of the jar that should be contained within them. The list of layers in the index is ordered based on the order in which the layers should be added to the Docker/OCI image. Out-of-the-box, the following layers are supported:

  • dependencies (for regular released dependencies)
  • spring-boot-loader (for everything under org/springframework/boot/loader)
  • snapshot-dependencies (for snapshot dependencies)
  • application (for application classes and resources)

The following shows an example of a layers.idx file:

1.2. Docker 鏡像分層

為了使得創建優化過的 Docker 鏡像更方便,Spring Boot 支持在 jar 包中增加一個分層索引文件。這個文件提供了一個分層列表以及各層應當包含的 jar 包的部分。該索引中的分層列表是根據各層添加至 Docker/OCI 鏡像的順序排列的。開箱即用,支持以下分層:

  • 依賴(定期發布的依賴項)
  • spring-boot-loader(在 org/springframework/boot/loader 目錄下的所有文件)
  • 快照依賴(快照版本的依賴項)
  • 應用程序(應用程序的類文件和資源文件)

下面展示了一個 layers.idx 文件的示例:

- "dependencies":
  - BOOT-INF/lib/library1.jar
  - BOOT-INF/lib/library2.jar
- "spring-boot-loader":
  - org/springframework/boot/loader/JarLauncher.class
  - org/springframework/boot/loader/jar/JarEntry.class
- "snapshot-dependencies":
  - BOOT-INF/lib/library3-SNAPSHOT.jar
- "application":
  - META-INF/MANIFEST.MF
  - BOOT-INF/classes/a/b/C.class

This layering is designed to separate code based on how likely it is to change between application builds. Library code is less likely to change between builds, so it is placed in its own layers to allow tooling to re-use the layers from cache. Application code is more likely to change between builds so it is isolated in a separate layer.

這種分層旨在根據代碼在應用程序多次構建之間發生更改的可能性大小將其分離開。庫代碼不太可能在多次構建中發生變化,所以將其放置在自己的分層中以允許工具重用緩存中的分層。應用代碼在多次構建中最可能發生改變,因此它被隔離在單獨的層中。

Spring Boot also supports layering for war files with the help of a layers.idx.

Spring Boot 也支持在 layers.idx 的支持下對 war 包文件進行分層。

For Maven, see the packaging layered jar or war section for more details on adding a layer index to the archive. For Gradle, see the packaging layered jar or war section of the Gradle plugin documentation.

對 Maven 而言,向歸檔文件內添加分層索引的更多細節參閱”打包分層的 jar 包或 war 包“部分。對 Gradle 而言,參閱 Gradle 插件文檔的”打包分層的 jar 包或 war 包“部分。

2. Dockerfiles
While it is possible to convert a Spring Boot fat jar into a docker image with just a few lines in the Dockerfile, we will use the layering feature to create an optimized docker image. When you create a jar containing the layers index file, the spring-boot-jarmode-layertools jar will be added as a dependency to your jar. With this jar on the classpath, you can launch your application in a special mode which allows the bootstrap code to run something entirely different from your application, for example, something that extracts the layers.

  1. Dockerfiles

雖然通過 Dockerfile 里的幾行命令就可以將一個 Spirng Boot 臃腫 jar 包轉換成 docker 鏡像,但我們將使用分層特性創建一個優化過的 docker 鏡像。當您創建一個包含分層索引文件的 jar 包時,spring-boot-jarmode-layertools 的 jar 包將被作為依賴項添加到您的 jar 包中。通過類路徑上的這個 jar 包,您可以在特殊模式下啟動您的程序:該模式允許引導代碼運行一些與您的代碼完全不同的東西,比如能夠提取分層信息的程序。

Caution
The layertools mode can not be used with a fully executable Spring Boot archive that includes a launch script. Disable launch script configuration when building a jar file that is intended to be used with layertools.

注意:

layertools 模式不能與包含啟動腳本的完全可執行 Spring Boot 歸檔文件一起使用。在要構建用於 layertools 的 jar 包文件時禁用啟動腳本配置。

Here's how you can launch your jar with a layertools jar mode:

這里展示了你怎么通過 layertools 模式啟動你的 jar 包

java -Djarmode=layertools -jar my-app.jar

This will provide the following output:

這會提供以下輸出信息:

Usage:
  java -Djarmode=layertools -jar my-app.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

The extract command can be used to easily split the application into layers to be added to the dockerfile. Here is an example of a Dockerfile using jarmode.

使用 extract 命令可以簡單的將應用程序拆分成各個要被添加至 dockerfile 的分層。下面是一個使用 jarmode 的 Dockerfile 示例:

FROM adoptopenjdk:11-jre-hotspot as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract

FROM adoptopenjdk:11-jre-hotspot
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/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

Assuming the above Dockerfile is in the current directory, your docker image can be built with docker build ., or optionally specifying the path to your application jar, as shown in the following example:

假設上面的 Dockerfile 文件位於當前目錄,您可以使用 docker build . 命令構建 docker 鏡像,或者可以指定應用程序的 jar 包路徑,如下例所示:

$ docker build --build-arg JAR_FILE=path/to/myapp.jar .

This is a multi-stage dockerfile. The builder stage extracts the directories that are needed later. Each of the COPY commands relates to the layers extracted by the jarmode.
Of course, a Dockerfile can be written without using the jarmode. You can use some combination of unzip and mv to move things to the right layer but jarmode simplifies that.

這是一個多階段的 dockerfile 。builder 階段提取下一個階段所需要的目錄。每一個 COPY 命令都與 jarmode 提取的分層相關。

當然,也可以在不使用 jarmode 的情況下編寫 Dockerfile 文件。您可以使用一些 unzipmv 命令的組合來將文件移動到對應的分層,但是 jarmode 簡化了這一過程。

  1. Cloud Native Buildpacks
    Dockerfiles are just one way to build docker images. Another way to build docker images is directly from your Maven or Gradle plugin, using buildpacks. If you’ve ever used an application platform such as Cloud Foundry or Heroku then you’ve probably used a buildpack. Buildpacks are the part of the platform that takes your application and converts it into something that the platform can actually run. For example, Cloud Foundry’s Java buildpack will notice that you’re pushing a .jar file and automatically add a relevant JRE.

Dockerfiles 只是構建 docker 鏡像的方法之一。而另一種方法是使用構建包直接從您的 Maven 或 Gradle 插件構建。如果您曾經使用過 Cloud Foundry 或者 Heroku 之類的應用平台,那么您可能使用過 buildpack。Buildpack 是平台的一部分,它獲取您的應用並且將其轉換為平台實際運行的東西。例如,Cloud Foundry 的 Java buildpack 會在您推送一個 .jar 文件的時候自動添加相關的 JRE。

With Cloud Native Buildpacks, you can create Docker compatible images that you can run anywhere. Spring Boot includes buildpack support directly for both Maven and Gradle. This means you can just type a single command and quickly get a sensible image into your locally running Docker daemon.
See the individual plugin documentation on how to use buildpacks with Maven and Gradle.

您可以通過使用 Cloud Native Buildpack 創建能在任何地方運行的 Docker 兼容鏡像。Spring Boot 包含對 Maven 以及 Gradle 的 buildpack 的直接支持。這意味着您可以僅僅通過輸入一條命令將一個合理的鏡像文件放入本地運行的 Docker daemon 中。

有關如何在 Maven 和 Gradle 中使用 buildpack ,請參閱相關的文檔。

Note
The Paketo Spring Boot buildpack has also been updated to support the layers.idx file so any customization that is applied to it will be reflected in the image created by the buildpack.

Paketo Spring Boot buildpack 也已經更新以支持 layers.idx 文件,因此任何應用於它的任何自定義設置都將反映在 buildpack 創建的鏡像中。

Note
In order to achieve reproducible builds and container image caching, Buildpacks can manipulate the application resources metadata (such as the file "last modified" information). You should ensure that your application does not rely on that metadata at runtime. Spring Boot can use that information when serving static resources, but this can be disabled with spring.web.resources.cache.use-last-modified

為了實現可重復的 build 以及容器鏡像緩存,Buildpack 可以操作應用程序的資源元數據(比如文件的“上次修改”信息)。您應該確保應用運行時不依賴於這類元數據。Spring Boot 會在服務靜態資源時使用這些信息,但可以通過spring.web.resources.cache.use-last-modified 來設置禁用。

4. What to Read Next
Once you’ve learned how to build efficient container images, you can read about deploying applications to a cloud platform, such as Kubernetes.

一旦您了解了如何構建高效的容器鏡像,您就可以閱讀有關將應用程序部署到雲平台(如 Kubernetes)的內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM