Efficient Container Images

将 Spring Boot uber jar 打包为 docker 映像非常简单。然而,按原样复制和运行 uber jar 在 docker 映像中有多种弊端。在不将其解包的情况下运行 uber jar 总会出现一定程度的开销,而在容器化环境中这可能会很明显。另一个问题是将你的应用程序代码及其所有依赖项放置在 Docker 映像中的一个层中不是最优的。由于你重新编译代码的频率可能高于你升级所用 Spring Boot 版本的频率,因此通常最好将内容分得更开。如果你在应用程序类之前将 jar 文件放置在层中,则 Docker 通常仅需更改最底层,即可从其缓存中选取其他内容。

Layering Docker Images

为了更轻松地创建优化的 Docker 映像,Spring Boot 支持将层索引文件添加到 jar 中。它提供了一系列层和应当包含在其中的 jar 部分。索引中的层列表是根据层应当添加到 Docker/OCI 映像的顺序排列的。开箱即用情况下,支持以下层:

  • dependencies(用于常规已发布的依赖项)

  • spring-boot-loader(用于 org/springframework/boot/loader 之下的所有内容)

  • snapshot-dependencies (for 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

这种分层旨在根据代码在应用程序构建之间发生变化的可能性对代码进行分离。库代码在不同构建之间的变化可能性较小,因此将其放置在其自身的层中,以允许工具从缓存中重新使用这些层。应用程序代码在不同构建之间的变化可能性较高,因此将其隔离在单独的层中。

借助 layers.idx 的帮助,Spring Boot 还支持 war 文件的分层。

对于 Maven,请参阅 packaging layered jar or war section 以了解有关向归档添加层索引的更多详细信息。对于 Gradle,请参阅 Gradle 插件文档的 packaging layered jar or war section