Java is one of the most used programming languages for enterprise application development globally. However, developers often struggle with the size of the Docker images when deploying Java applications in Docker containers. One of the ways to solve this problem is to use JLink, a tool introduced in JDK 9.
JLink (Java Linker) is a command-line tool that assembles and optimizes a set of modules and their dependencies into a custom runtime image. This essentially means it creates a minimal Java runtime environment with only the necessary modules required by your application.
jlink --module-path $JAVA_HOME/jmods:mlib --add-modules test.module --output testRunTime
In the above command, test.module
is your module, and testRuntime
is the custom runtime image that JLink will create.
When creating Docker images for Java applications, the size of the image is often a concern — particularly for Spring Boot applications, which come with many dependencies.
JLink enables you to create a minimal Java runtime with only the necessary modules. By doing so, it significantly reduces the size of your Docker image. For example, a standard Java runtime environment might be over 200 MB, but with JLink, you can bring it down to less than 50 MB.
Jdeps is a Java tool that shows the package-level or class-level dependencies. The tool, introduced in Java 8, can be used to understand an application’s dependencies, which can then be used to create a custom runtime image using JLink.
When ensuring that all our dependencies are located in one directory, we can use jdeps to print a summary of the dependencies.
jdeps -cp 'mydeps/lib/*' -recursive --multi-release 17 -s target/MyJar.jar
Similarly, we can use jdeps to print all module dependencies recursively for the Spring Boot application and the dependencies. The output generated by jdeps enables JLink to create a Java Runtime that only contains the modules needed for this application.
So now, let’s combine jdeps and JLink to build a custom Java Runtime. With this runtime, we can create a perfect, minimal Docker image specifically for a Spring Boot application.
FROM maven:3-eclipse-temurin-17 as build
COPY ./build/libs/*.jar app.jar
RUN jdeps --ignore-missing-deps -q \
--recursive \
--multi-release 17 \
--print-module-deps \
--class-path 'BOOT-INF/lib/*' \
app.jar > deps.info
RUN jlink \
--add-modules $(cat deps.info) \
--strip-debug \
--compress 2 \
--no-header-files \
--no-man-pages \
--output /myjre
ENTRYPOINT ["java","-jar","/app.jar"]
The example above lightens the image for the jar file docker build in a typical location in a spring application.
reference