最小のJREを使っているスリムなDocker Javaイメージをつくる方法


これは、here
このポストでは、カスタマイズされたJRESをjlinkjmodsを使用して作成することで、スリムなDockerイメージを作成できる方法を説明します.
これらのコマンドはJava 9からJDKに存在しますが、Java 11以降十分に成熟しているので、Javaから必要なモジュールだけを使用してカスタマイズされたJREを作成し、Javaアプリケーションを実行するためのより小さなDockerイメージを作成する新しい方法を提供します(主に春のブートアプリケーションにフォーカスします).あなたのコンテナーリポジトリアプリケーション(ECR、アーティファクト、Dockerハブ)でいくつかの良いドルを節約.

でも、どうやって始めるの?


既にマシンにインストールされているJDKを持っていると仮定した場合、sdkman.ioを使用してJava 17バージョンをインストールすることを強く推奨します(最新のLTSはこの投稿の日付です).
まず第一に、私たちはあなたのJarfileに基づくjdepsから湧き出したブートリストから生成されたリストを得る必要があります.
$ jdeps --list-deps --ignore-missing-deps  your-fat-jar.jar
   java.base
   java.logging
まあ、それは右のようではないですか?
Spring Bootは、デフォルトではすべての必要な依存関係を持つFAT jarを生成するための戦略を持っています.そして、jdepsは現在、すべての依存関係をFAT jarからjarファイル内で再帰的に取得できません.
それで、あなたがすることができることはFATジャーからすべての内容を抽出して、libフォルダのあらゆるjarに対してjdepsを走らせることです.
または、試行錯誤を試みることができますし、各JREのバージョンから取得されますどのクラスのFoundNextExceptionを参照してください
しかし、いくつかの以前の経験から、我々は通常、我々の最小限のJREでこれらのパッケージを必要とします:
java.compiler
java.logging
java.sql
java.rmi
java.naming
java.management
java.instrument
java.security.jgss
java.net.http
jdk.httpserver
jdk.naming.dns
しかし、私の提案はあなた自身を試して、あなたが本当にあなたのスリムなJRE

Java Slim JREの作成


カスタマイズされたJREを作成するには、jlinkをローカルで使用できます.
jlink \
    --module-path "$JAVA_HOME/jmods" \
    --add-modules [the java modules your application needs joined by ,] \
    --verbose \
    --strip-debug \
    --compress 2 \
    --no-header-files \
    --no-man-pages \
    --output /opt/jre-minimal
各フラグの説明
--module-path <path>              Module path.
                                        If not specified, the JDKs jmods directory
                                        will be used, if it exists. If specified,
                                        but it does not contain the java.base module,
                                        the JDKs jmods directory will be added,
                                        if it exists.

--verbose                         Enable verbose tracing

--strip-debug                     Strip debug information

--compress=<0|1|2>                Enable compression of resources:
                                          Level 0: No compression
                                          Level 1: Constant string sharing
                                          Level 2: ZIP

--no-header-files                 Exclude include header files

--no-man-pages                    Exclude man pages

--output <path>                   Location of output path
あなたのコマンドラインツールでjlinks --helpを実行して、これらの情報を得ることができます.

しかし、どのように私は私のスリムスプリングブートアプリケーションのDockerイメージを作成する


さて、私が言及したように、これを例にしてください.これはOpenJDK 17のバージョン(この記事が書かれた時点で最新のLTS)を使用しています
# Build our minimal JRE using jlink

FROM openjdk:17-oraclelinux8 as builder

USER root

RUN jlink \
    --module-path "$JAVA_HOME/jmods" \
    --add-modules java.compiler,java.sql,java.naming,java.management,java.instrument,java.rmi,java.desktop,jdk.internal.vm.compiler.management,java.xml.crypto,java.scripting,java.security.jgss,jdk.httpserver,java.net.http,jdk.naming.dns,jdk.crypto.cryptoki,jdk.unsupported \
    --verbose \
    --strip-debug \
    --compress 2 \
    --no-header-files \
    --no-man-pages \
    --output /opt/jre-minimal

USER app

# Now it is time for us to build our real image on top of an slim version of debian

FROM debian:stretch-slim

COPY --from=builder /opt/jre-minimal /opt/jre-minimal

ENV JAVA_HOME=/opt/jre-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"

VOLUME /tmp

# Copy the JRE created in the last step into our $JAVA_HOME

# For gradle
# COPY build/libs/app-*.jar app.jar

# For maven
# COPY target/app-*.jar app.jar


ENTRYPOINT ["java","-jar","/app.jar"] 
しかし、これはどのように効率的ですか?
たとえば、通常の春のブートアプリケーションでは、すべての画像のためのストレージの200 MBを保存し、543.03から349.98まで、あなたのコンテナーレジストリ内のアプリケーションの10のバージョンを常に持っていると仮定すると、各アプリケーションの2 GBのストレージスペースを保存することができます!
このrepoの例を確認できます