[JAVA] 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. 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.

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/

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.

  1. 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 .
  1. Deploy Rewrite the kubernetes configuration file and deploy it.
$ kubectl apply -f kubernetes

Reference

Recommended Posts

How to create a small docker image of openjdk 11 (ea) application (1GB → 85MB)
How to deploy to Heroku from a local docker image
How to create a method
How to create a lightweight container image for Java apps
[Personal notes] How to push a Docker image to GitHub Packages
Create a lightweight STNS Docker image
Preparing to create a Rails application
[Java] How to create a folder
Use Jenkins to build inside Docker and then create a Docker image.
How to quickly create a reverse proxy that supports HTTPS with Docker
How to create a Maven repository for 2020
[Docker] How to create a virtual environment for Rails and Nuxt.js apps
[Swift5] How to create a splash screen
[rails] How to create a partial template
Volume of trying to create a Java Web application on Windows Server 2016
How to migrate a web application created in a local docker environment to AWS
Docker Compact Manual (4: Create a custom image)
[Introduction to Docker] Create a Docker image for machine learning and use Jupyter notebook
How to create a database for H2 Database anywhere
Summary of how to create JSF self-made tags
[Rails] How to create a graph using lazy_high_charts
How to get a heapdump from a Docker container
How to make Spring Boot Docker Image smaller
How to create pagination for a "kaminari" array
How to create a class that inherits class information
How to create a theme in Liferay 7 / DXP
How to give your image to someone with docker
[1st] How to create a Spring-MVC framework project
How to easily create a pull-down in Rails
[Rails] How to create a Twitter share button
How to install Docker in the local environment of an existing Rails application [Rails 6 / MySQL 8]
I tried using Wercker to create and publish a Docker image that launches GlassFish 5.
[Docker] How to see the contents of Volumes. Start a container with root privileges.
I made a Docker image of SDAPS for Japanese
Create a docker image that runs a simple Java app
[Introduction] Try to create a Ruby on Rails application
How to create a Java environment in just 3 seconds
[Rails] How to create a signed URL for CloudFront
How to create a JDBC URL (Oracle Database, Thin)
Weight reduction of Docker image by multi-stage build-React application
How to create a Spring Boot project in IntelliJ
[Spring Boot] How to create a project (for beginners)
How to create a data URI (base64) in Java
Create a Docker container to convert EPS to PGF source
Mandels to create an image of the Mandelbrot set
[Rails 6] How to set a background image in Rails [CSS]
How to judge the click of any area of the image
[Apple Subscription Offer] How to create a promotional offer signature
If you want to make a Java application a Docker image, it is convenient to use jib.
How to install Docker
How to create docker-compose
Create a Docker image with the Oracle JDK installed (yum
How to create an application server on an EC2 instance on AWS
How to create a form to select a date from the calendar
How to create a placeholder part to use in the IN clause
How to Burning a Install Disk of Windows from Ubuntu
A series of steps to create portfolio deliverables with Rails
How to move another class with a button action of another class.
[Ruby] How to retrieve the contents of a double hash
How to create a service builder portlet in Liferay 7 / DXP
I tried to create a padrino development environment with Docker