高效的容器映像檔

將 Spring Boot uber jar 封裝成 Docker 映像檔相當容易。然而,直接複製並執行 uber jar 在 Docker 映像檔中有一些缺點。在不解壓的情況下執行 uber jar 總是會有一定的額外負擔,在容器化環境中,這個負擔可能會很明顯。另一個問題是將應用程式程式碼及其所有相依性放在 Docker 映像檔的單一層中並非最佳做法。由於您重新編譯程式碼的頻率可能比升級 Spring Boot 版本的頻率更高,因此將它們稍微分開通常會更好。如果您將 jar 檔案放在應用程式類別之前的層中,Docker 通常只需要更改最底層,就可以從其快取中提取其他層。

Docker 映像檔分層

為了更容易建立優化的 Docker 映像檔,Spring Boot 支援在 jar 中新增一個層索引檔案。它提供了一個層列表以及 jar 中應包含在每個層中的部分。索引中的層列表是根據將層新增到 Docker/OCI 映像檔的順序排列的。預設情況下,支援以下層:

  • dependencies(適用於正式發布的相依性)

  • spring-boot-loader(適用於 org/springframework/boot/loader 下的所有內容)

  • snapshot-dependencies(適用於快照版相依性)

  • application(適用於應用程式類別和資源)

以下顯示了一個 layers.idx 檔案的範例

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

這種分層設計旨在根據應用程式建置之間的變更可能性來區分程式碼。函式庫程式碼在建置之間不太可能變更,因此它被放置在自己的層中,以便工具可以重複使用快取中的層。應用程式程式碼在建置之間更有可能變更,因此它被隔離在一個單獨的層中。

Spring Boot 也在 layers.idx 的幫助下支援 war 檔案的分層。

對於 Maven,請參閱封裝分層 jar 或 war 章節,以瞭解更多關於將層索引新增到封存的詳細資訊。對於 Gradle,請參閱 Gradle 外掛程式文件的封裝分層 jar 或 war 章節