Introduction This is a translation of the following document into English. Since the dokcer image (1GB) of OpenJDK11 is large, create a small image (85MB) with alpine linux + jlink
I am not good at English. I would be happy if you point out some strange sentences.
Goal The goal is to reduce the file size of the docker image of the java application.
I will create an environment that moves the following.
Result
The size of 1 GB has been reduced to about 85 MB.
Image size is the result output by the docker images command.
| image type | jlink | size | 
|---|---|---|
| openjdk:11-jdk | not used | 1GB | 
| openjdk:11-jdk | used | 468MB | 
| hirokimatsumoto/alpine-openjdk-11 | not used | 336MB | 
| hirokimatsumoto/alpine-openjdk-11 | used | 84.6MB | 
hirokimatsumoto/alpine-openjdk-11 is https://hub.docker.com/r/hirokimatsumoto/alpine-openjdk-11/
openjdk is https://hub.docker.com/_/openjdk/
Background problem The docker image of openjdk 11 is published in the official respoitory of docker hub. https://hub.docker.com/_/openjdk/
This image has the following problem.
openjdk:11-jdk tag image size is large. There is about 1 GB.jre tag images.The file size was confirmed with the following command.
$ sudo docker images |grep jdk
docker.io/openjdk                            11-jdk   f684efd78557  2 weeks ago         979 MB
$
I confirmed that libjvm.so becomes larger when using jlink.
$ docker run -it --rm openjdk:11-jdk /bin/sh
# ls -l /usr/lib/jvm/java-11-openjdk-amd64/lib/server/
total 34944
-rw-r--r-- 1 root root     1322 Jul 27 03:41 Xusage.txt
-r--r--r-- 1 root root 18210816 Jul 27 22:22 classes.jsa
-rw-r--r-- 1 root root    14440 Jul 27 03:41 libjsig.so
-rw-r--r-- 1 root root 17551048 Jul 27 03:41 libjvm.so
# jlink \
     --module-path /opt/java/jmods \
     --compress=2 \
     --add-modules java.base,java.logging,jdk.jfr  \
     --no-header-files \
     --no-man-pages \
     --output /opt/jdk-11-mini-runtime
#  ls -l /opt/jdk-11-mini-runtime/lib/server/
total 414452
-rw-r--r-- 1 root root      1322 Aug 14 09:41 Xusage.txt
-rw-r--r-- 1 root root     25384 Aug 14 09:41 libjsig.so
-rw-r--r-- 1 root root 424362808 Aug 14 09:41 libjvm.so
#
The generated libjvm.so increased to 424 MB. This problem is probably part of the following issue issue. https://github.com/docker-library/openjdk/issues/217
How to build small image
https://hub.docker.com/r/hirokimatsumoto/alpine-openjdk-11/
FROM alpine:3.8
RUN mkdir /opt; cd /opt; \
    wget https://download.java.net/java/early_access/alpine/25/binaries/openjdk-11-ea+25_linux-x64-musl_bin.tar.gz \
    && tar zxf openjdk-11-ea+25_linux-x64-musl_bin.tar.gz \
    && ln -s jdk-11 java \
    && rm -f openjdk-11-ea+25_linux-x64-musl_bin.tar.gz
ENV JAVA_HOME=/opt/java
ENV PATH="$PATH:$JAVA_HOME/bin"
I should use checksum, but it is not.
The target application is https://github.com/h-r-k-matsumoto/k8s-jmc-sample
FROM hirokimatsumoto/alpine-openjdk-11:latest as jlink-package
# First: generate java runtime module by jlink.
RUN jlink \
     --module-path /opt/java/jmods \
     --compress=2 \
     --add-modules jdk.jfr,jdk.management.agent,java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
     --no-header-files \
     --no-man-pages \
     --output /opt/jdk-11-mini-runtime
# Second: generate run image.
FROM alpine:3.8
ENV JAVA_HOME=/opt/jdk-11-mini-runtime
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=jlink-package /opt/jdk-11-mini-runtime /opt/jdk-11-mini-runtime
COPY target/k8s-jmc-sample-0.1.0-SNAPSHOT.jar /opt/spring-boot/
EXPOSE 30001 7199
CMD java \
    -XX:StartFlightRecording=name=sample,filename=/spring-boot/jfr/sample.jfr,delay=30s,maxage=2h,maxsize=10m,dumponexit=true,settings=/spring-boot/config/profile.jfc \
    -Dcom.sun.management.jmxremote.port=7199 \
    -Dcom.sun.management.jmxremote.rmi.port=7199 \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false \
    -jar /opt/spring-boot/k8s-jmc-sample-0.1.0-SNAPSHOT.jar \
    --server.port=${SPRING_SERVER_PORT} \
    --spring.config.location=/spring-boot/config/application.yaml
$ mvn clean package
$ docker build  -t  gcr.io/prod-bl-cloud/k8s-jmc-sample:java11-mini-runtime .
$ kubectl apply -f kubernetes
Reference
Recommended Posts