高效容器镜像

将 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 部分