LoginSignup
9
2

More than 5 years have passed since last update.

How to create a small docker image of openjdk 11(ea) application ( 1GB→85MB )

Last updated at Posted at 2018-08-14

Introduction

This is a translation of the following document into English.
OpenJDK11のdokcerイメージ(1GB)が大きいのでalpine linux+ jlinkで小さいイメージ(85MB)を作成する

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

9
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2