How JLink Can Help You Build Smaller Java Docker Images

  • 2025/1/10
  • Comments Off on How JLink Can Help You Build Smaller Java Docker Images

Java is a popular programming language, but when we need to deploy Java applications in containers like Docker, the size of the Docker image can become a problem. Docker images that include the entire Java Runtime Environment (JRE) can become quite large. This can slow down downloads and deployments.

One solution to this problem is JLink. In this blog, we’ll explain what JLink is, how it works, and how it can help you build smaller Docker images. We’ll also walk through a simple example of using JLink to create a custom Java runtime for a Docker app.

What is JLink?

JLink is a command-line tool introduced in Java 9 that helps developers create smaller Java runtime environments (JREs). Normally, when you package a Java application, you include a full JRE, which can be quite large. With JLink, you can create a custom JRE that only includes the parts (modules) your application actually needs.

The benefit of JLink is that it lets you reduce the size of your Docker image by leaving out unnecessary Java components. This results in faster downloads, smaller image sizes, and more efficient deployments.

How Does JLink Work?

JLink works by allowing you to choose specific Java modules that your application needs. For example, if your app doesn’t use JavaFX or some other modules, you can leave those out. Here’s a simple breakdown of how JLink works:

  1. Choose the Required Modules: Identify which parts of Java your app needs.
  2. Create a Custom JRE: JLink creates a smaller JRE containing just those modules.
  3. Package Your App: Package your Java app along with this slimmed-down JRE.

Let’s start our example

Assume we have a Spring Boot application and a Dockerfile like below:

FROM eclipse-temurin:21.0.5_11-jdk-alpine AS builder
WORKDIR /app
COPY gradle /app/gradle
COPY gradlew /app/gradlew
COPY build.gradle /app/build.gradle
COPY settings.gradle /app/settings.gradle
COPY src /app/src
RUN ./gradlew build -x test
ENTRYPOINT [ "java", "-jar", "build/libs/demo-0.0.1-SNAPSHOT.jar" ]

After building the image, we can see that the size is about 603MB although we used alpine version to reduce it.

Okay. Let’s change the Dockerfile commands with Jlink.

FROM eclipse-temurin:21.0.5_11-jdk-alpine AS builder
WORKDIR /opt
RUN $JAVA_HOME/bin/jlink \
--add-modules ALL-MODULE-PATH \
--strip-debug \
--no-man-pages \
--no-header-files \
--compress=2 \
--output /opt/jdk


FROM alpine:latest AS runtime
COPY --from=builder /opt/jdk /opt/jdk
ENV JAVA_HOME=/opt/jdk
ENV PATH="$JAVA_HOME/bin:$PATH"
COPY build/libs/demo-0.0.1-SNAPSHOT.jar app.jar
CMD ["java", "-jar", "/app.jar"]

Let’s check the image after build

Amazing! The image jlink-demo:1.1 now is only 127MB which is smaller than the jlink-demo:1.0 almost 5 times.

The reason is that we used the Jlink command to install a new runtime which was based on depenencies of our application. More in details:

  • RUN $JAVA_HOME/bin/jlink \: This is a Dockerfile instruction that runs the jlink command. $JAVA_HOME/bin/jlink specifies the path to the jlink executable within the Java installation.
  • --add-modules ALL-MODULE-PATH \: This option includes all modules present in the module path in the custom runtime image.
  • --strip-debug \: This option removes debugging information from the generated runtime image to reduce its size.
  • --no-man-pages \: This option excludes the man pages from the runtime image to save space.
  • --no-header-files \: This option excludes the header files from the runtime image to save space.
  • --compress=2 \: This option compresses the files in the runtime image using ZIP compression level 2, which is a balance between speed and compression ratio.
  • --output /opt/jdk: This specifies the output directory for the generated custom runtime image, which in this case is /opt/jdk.

Overall, this command creates a minimized, custom Java runtime image tailored to the application, reducing its size by stripping unnecessary components.

Conclusion

In this blog post, we’ve explored JLink, a tool introduced in Java 9 that lets you create a smaller, custom Java runtime. We discussed how JLink works, its benefits (like reducing Docker image size and improving performance), and walked through a simple example to show how it’s done.

Using JLink to create a custom runtime for your Java app can lead to smaller Docker images, faster startups, and better security. It’s a great way to make your Java applications more efficient and easier to deploy in containers.

この情報は役に立ちましたか?


フィードバックをいただき、ありがとうございました!

関連記事

カテゴリー:

ブログ

情シス求人

  1. チームメンバーで作字やってみた#1

ページ上部へ戻る