[JAVA] Since the dokcer image (1GB) of OpenJDK11 is large, create a small image (85MB) with alpine linux + jlink.

Introduction

The docker image of openjdk 11 is published in the official respoitory of docker hub.

https://hub.docker.com/_/openjdk/

But ... I'm a little worried about using this

--The image size is large in the first place. There is also about 1GB. --Even with jlink, there is more than 300MB

There is a problem. I want to make it smaller. So I tried how small it could be!

Premise

--Java Flight Recorder works --Spring Boot application works

result

** 1GB → 85MB and could be compressed to less than 1/10: grinning: ** Personally, I am very satisfied.

The result of checking the size with docker images is as follows.

Image type Use jlink size
openjdk:11-jdk do not do 1GB
openjdk:11-jdk To do 468MB
Original alpine linux do not do 336MB
Original alpine linux To do 84.6MB

jdk11 is an ea version. I think that it will be possible to make a small image with the official image of openjdk 11 properly. Original alpinelinux,  https://hub.docker.com/r/hirokimatsumoto/alpine-openjdk-11/ is.

problem

Details the issue of the official image of OpenJDK 11.

Large image size

$ sudo docker images |grep jdk
docker.io/openjdk                            11-jdk   f684efd78557  2 weeks ago         979 MB
$

The flight recorder doesn't work on jre, so I want to use jdk ... it's a little too big. Reference: [Qiita --OpenJDK11-JRE-SLIM does not work Flight Recorder. ](Https://qiita.com/hrk-matsumoto/items/ca1a6d80f3984c975c20#openjdk11-jre-slim%E3%81%98%E3%82%83flightrecorder%E3%81%AF%E5%8B%95%E3% 81% 8D% E3% 81% BE% E3% 81% 9B% E3% 82% 93)

In openjdk 11 (official), it doesn't get smaller even if you use jlink.

The issue below addresses the same issue. https://github.com/docker-library/openjdk/issues/217

When I try it ... For some reason, it becomes about 400MB and the image size becomes about 450MB as shown below.

$ 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  #Still small
Try to compress
# 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 #why···
#

I'll reduce the image size!

Let's take the approach of using alpine linux and then using jlink to make it smaller.

Create an image for build based on alpine linux.

Can other people stand about? I think it is open to the public.

image: https://hub.docker.com/r/hirokimatsumoto/alpine-openjdk-11/ docker file: https://hub.docker.com/r/hirokimatsumoto/alpine-openjdk-11/~/dockerfile/

I'm sorry I didn't checksum ...

Create a small execution image using jlink.

Build using multi stage.

  1. Based on the image of alpine linux + openjdk 11 created above, create a small java runtime module with jlink.
  2. Create an image of alphine linux that is a copy of the runtime module and jar module.
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

Execution application https://github.com/h-r-k-matsumoto/k8s-jmc-sample is.

I was addicted to

Looking at the dependencies of a Spring Boot application with jdeps is not accurate

First, I used jdeps to check the required modules as shown below.

> jdeps --list-deps .\target\k8s-jmc-sample-0.1.0-SNAPSHOT.jar
   java.base
   java.logging
>

Even if you make a runtime with this ... At the time of execution, an error will occur as shown below.

Caused by: java.lang.ClassNotFoundException: java.sql.SQLException
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)

Hmmm, I wonder if I can't track the auto-configured part inside spring boot well ... It was annoying, so  https://dev.solita.fi/2018/01/24/Java9-modules-Spring-Boot-2-Docker.html I added it appropriately.

reference

Recommended Posts

Since the dokcer image (1GB) of OpenJDK11 is large, create a small image (85MB) with alpine linux + jlink.
[AWS Lambda] Create a deployment package using the Docker image of Amazon Linux
What to do when a part of the background image becomes transparent when the transparent image is combined with Pillow
The image is a slug
[Statistics] Grasp the image of the central limit theorem with a graph
On Linux, the time stamp of a file is a little past.
[Go] Create a CLI command to change the extension of the image
Create a Docker container image with JRE8 / JDK8 on Amazon Linux
Create a compatibility judgment program with the random module of python.
I tried to easily create a high-precision 3D image with one photo [-1]. (Is the hidden area really visible?)