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

# 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

https://hub.docker.com/r/hirokimatsumoto/alpine-openjdk-11/

```Dockerfile
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

```Dockerfile
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
```

```build
$ mvn clean package
$ docker build  -t  gcr.io/prod-bl-cloud/k8s-jmc-sample:java11-mini-runtime .
```

## 3. Deploy
Rewrite the [kubernetes configuration file](https://github.com/h-r-k-matsumoto/k8s-jmc-sample/tree/master/kubernetes) and deploy it.

```apply
$ 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