@ -7703,6 +7703,154 @@ If you need the `Mockk` equivalent of the Mockito specific <<boot-features-testi
[[building-docker-images]]
=== Building Docker Images
Spring Boot applications can be containerized by packaging them into Docker images.
A typical Spring Boot fat jar can be converted into a Docker image by adding just a few lines to a Dockerfile that can be used to build the 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 it's 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.
==== Layered Jars
To make it easier to create optimized Docker images that can be built with a dockerfile, Spring Boot supports "layered jars".
A regular fat jar that can be run with `java -jar` has the following structure:
[source]
----
META-INF/
MANIFEST.MF
org/
springframework/
boot/
loader/
...
BOOT-INF/
classes/
...
lib/
...
----
The jar is organized into three main parts:
* Classes used to bootstrap jar loading
* Your application classes in `BOOT-INF/classes`
* Dependencies in `BOOT-INF/lib`
Instead of the above jar, you can create a layered jar that looks something like this:
[source]
----
META-INF/
MANIFEST.MF
org/
springframework/
boot/
loader/
...
BOOT-INF/
layers/
<name>/
classes/
...
lib/
...
<name>/
classes/
...
lib/
...
layers.idx
----
You still see the bootstrap loader classes (you can still run `java -jar`) but now the `lib` and `classes` folders have been split up and categorized into layers.
There’s also a `layers.idx` file that provides the order in which layers should be added.
Out-of-the-box, the following layers are supported:
* `dependencies` (for regular released dependencies)
* `application` (for application classes and resources)
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.
For Maven, layered jars can be created using a new `layout` type called `LAYERED_JAR`.
See the {spring-boot-maven-plugin-docs}/#goals-build-image-parameters-details-layout[layout section] for more details.
For Gradle, refer to the {spring-boot-gradle-plugin-docs}/#packaging-layered-jars[packaging layered jars section] of the Gradle plugin documentation.
==== Writing the Dockerfile
When you create a layered jar, the `spring-boot-layertools` jar will be added as a dependency to your jar.
With this jar on the classpath, you can launch your application in a special mode which allows the bootstrap code to run something entirely different from your application, for example, something that extracts the layers.
Here’s how you can launch your jar with a `layertools` jar mode:
[source]
----
$ java -Djarmode=layertools -jar my-app.jar
----
This will provide the following output:
[source]
----
Usage:
java -Djarmode=layertools -jar my-app.jar
Available commands:
list List layers from the jar that can be extracted
extract Extracts layers from the jar for image creation
help Help about any command
----
The `extract` command can be used to easily split the application into layers to be added to the dockerfile.
Here's an example of a Dockerfile using `jarmode`.
[source]
----
FROM adoptopenjdk:11-jre-hotspot as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
The builder stage extracts the folders that are needed later.
Each of the `COPY` commands relates to the layers extracted by the jarmode.
Of course, a Dockerfile can be written without using the jarmode.
You can use some combination of `unzip` and `mv` to move things to the right layer but jarmode simplifies that.
==== Buildpacks
Dockerfiles are just one way to build docker images.
Another way to build docker images is directly from your Maven or Gradle plugin, using buildpacks.
If you’ve ever used an application platform such as Cloud Foundry or Heroku then you’ve probably used a buildpack.
Buildpacks are the part of the platform that takes your application and converts it into something that the platform can actually run.
For example, Cloud Foundry’s Java buildpack will notice that you’re pushing a `.jar` file and automatically add a relevant JRE.
With Cloud Native Buildpacks, you can create Docker compatible images that you can run anywhere.
Spring Boot includes buildpack support directly for both Maven and Gradle.
This means you can just type a single command and quickly get a sensible image into your locally running Docker daemon.
Refer to the individual plugin documentation on how to use buildpacks with {spring-boot-maven-plugin-docs}/#build-image[Maven] and {spring-boot-gradle-plugin-docs}/#packaging-oci-images[Gradle].
[[boot-features-whats-next]]
== What to Read Next
If you want to learn more about any of the classes discussed in this section, you can check out the {spring-boot-api}[Spring Boot API documentation] or you can browse the {spring-boot-code}[source code directly].