[[packaging.container-images.dockerfiles]]
= Dockerfiles

While it is possible to convert a Spring Boot uber jar into a Docker image with just a few lines in the `Dockerfile`, using the xref:packaging/container-images/efficient-images.adoc#packaging.container-images.efficient-images.layering[layering feature] will result in an optimized image.
When you create a jar containing the layers index file, the `spring-boot-jarmode-tools` 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.

CAUTION: The `tools` mode can not be used with a xref:how-to:deployment/installing.adoc[fully executable Spring Boot archive] that includes a launch script.
Disable launch script configuration when building a jar file that is intended to be used with the `extract` tools mode command.

Here’s how you can launch your jar with a `tools` jar mode:

[source,shell]
----
$ java -Djarmode=tools -jar my-app.jar
----

This will provide the following output:

[subs="verbatim"]
----
Usage:
  java -Djarmode=tools -jar my-app.jar

Available commands:
  extract      Extract the contents from the jar
  list-layers  List layers from the jar that can be extracted
  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 is an example of a `Dockerfile` using `jarmode`.

[source,dockerfile]
----
include::reference:partial$dockerfile[]
# Start the application jar - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and CDS/AOT cache friendly
ENTRYPOINT ["java", "-jar", "application.jar"]
----

Assuming the above `Dockerfile` is in the current directory, your Docker image can be built with `docker build .`, or optionally specifying the path to your application jar, as shown in the following example:

[source,shell]
----
$ docker build --build-arg JAR_FILE=path/to/myapp.jar .
----

This is a multi-stage `Dockerfile`.
The builder stage extracts the directories 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.
Additionally, the layout created by the `jarmode` is CDS and AOT cache friendly out of the box.



[[packaging.container-images.dockerfiles.cds]]
== CDS

If you want to additionally enable xref:reference:packaging/class-data-sharing.adoc#packaging.class-data-sharing.cds[CDS], you can use this `Dockerfile`:
[source,dockerfile]
----
include::reference:partial$dockerfile[]
# Execute the CDS training run
RUN java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar application.jar
# Start the application jar with CDS enabled - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and CDS friendly
ENTRYPOINT ["java", "-XX:SharedArchiveFile=application.jsa", "-jar", "application.jar"]
----

This is mostly the same as the above `Dockerfile`.
As the last steps, it creates the CDS archive by doing a training run and passes the CDS parameter to `java -jar`.

[[packaging.container-images.dockerfiles.aot-cache]]
== AOT cache

If you want to additionally enable the xref:reference:packaging/class-data-sharing.adoc#packaging.class-data-sharing.aot-cache[AOT cache], you can use this `Dockerfile`:
[source,dockerfile]
----
include::reference:partial$dockerfile[]
# Execute the AOT cache training run
RUN java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -Dspring.context.exit=onRefresh -jar application.jar
RUN java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -jar application.jar && rm app.aotconf
# Start the application jar with AOT cache enabled - this is not the uber jar used by the builder
# This jar only contains application code and references to the extracted jar files
# This layout is efficient to start up and AOT cache friendly
ENTRYPOINT ["java", "-XX:AOTCache=app.aot", "-jar", "application.jar"]
----

This is mostly the same as the above `Dockerfile`.
As the last steps, it creates the AOT cache file by doing a training run and passes the AOT cache parameter to `java -jar`.
