
Update documentation to replace "refer to" with "see" and to drop "please" when it is present. See gh-28537
77 lines
4.0 KiB
Plaintext
77 lines
4.0 KiB
Plaintext
[[container-images.efficient-images]]
|
||
== 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.
|
||
|
||
|
||
[[container-images.efficient-images.unpacking]]
|
||
=== 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:
|
||
|
||
[source,shell,indent=0,subs="verbatim"]
|
||
----
|
||
$ 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.
|
||
|
||
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:
|
||
|
||
[source,shell,indent=0,subs="verbatim"]
|
||
----
|
||
$ 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.
|
||
|
||
|
||
|
||
[[container-images.efficient-images.layering]]
|
||
=== 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:
|
||
|
||
[source,yaml,indent=0,subs="verbatim"]
|
||
----
|
||
- "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`.
|
||
|
||
For Maven, see the {spring-boot-maven-plugin-docs}#repackage-layers[packaging layered jar or war section] for more details on adding a layer index to the archive.
|
||
For Gradle, see the {spring-boot-gradle-plugin-docs}#packaging-layered-archives[packaging layered jar or war section] of the Gradle plugin documentation.
|