Introduction
This is a translation of the following document into English.
[OpenJDK11のdokcerイメージ(1GB)が大きいのでalpine linux+ jlinkで小さいイメージ(85MB)を作成する] (https://qiita.com/h-r-k-matsumoto/items/294eeb838cfd062d75b6)
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.
- Java Flight Recorder works.
- Spring Boot 2.0.X application to work
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. - Even if you use jlink, image size is 400 MB.
- Java Flight Recorder does not work in
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
1. Create an environment that uses jlink on alpine linux
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.
2. Build Application Image using jlink.
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 .
3. Deploy
Rewrite the kubernetes configuration file and deploy it.
$ kubectl apply -f kubernetes
Reference
- OpenJDK11: http://jdk.java.net/11/
- OpenJDK docker image issue: https://github.com/docker-library/openjdk/issues/217
- Spring Boot jlink: https://dev.solita.fi/2018/01/24/Java9-modules-Spring-Boot-2-Docker.html