高效的容器镜像

将 Spring Boot uber jar 打包为 Docker 镜像很容易。 但是,在 Docker 镜像中直接复制和运行 uber jar 有各种缺点。 在不解包的情况下运行 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 部分