[解決済み] Java 11 アプリケーションを軽量な docker イメージで提供
質問
質問から発想する なぜJava 11のベースDockerイメージはこんなに大きいのですか?(openjdk:11-jre-slim) Java界隈のこのトピックはまだ決着がついていないことがわかりました。
については
07 Dec 2018
については、共通の問題/落とし穴があります (上記のチケットで説明されています)。
-
JRE は個別の "パッケージ" として配布されません。代わりに JDK のモジュールを使用する必要があります。
-
オラクルOpenJDK 11 はサポートしません。 Linux アルパイン ということで 軽量 の画像を簡単に作成することはできません。
- 同時に、現在の Debian 安定版にはまだ Java 11 パッケージ ( UbuntuにはJava 10がインストールされています は openjdk-11 パッケージの下にインストールされています)、そのため不安定な sid バージョンがベースとなる docker イメージに使用されています。
-
現在利用可能な Oracle openjdk-11 イメージは、ストリップされていない状態でビルドされます。
libjvm.so
モジュールは数百メガバイトあり、別途ストリップする必要があります。
これらの問題の結果 スリム Oracle Java 11 の基本イメージはかなり重く、不安定であると考えられています。 https://hub.docker.com/_/openjdk/
ということで、質問です。
は何ですか? 最適化された または 推奨 Java 11 アプリケーションを docker イメージとして構築し配信する方法 ?
どのように解決するのですか?
2019年7月よりUPD : https://stackoverflow.com/a/57145029/907576
単純な Spring Boot アプリケーション (REST エンドポイントが 1 つだけ) を例にとると、今のところ次のような解決策があります (アプリケーションの jar が
build/libs/spring-boot-demo.jar
にあると仮定します。
-
ジェダイ・パス を使いたい場合は 公式の Oracle OpenJDK ディストリビューションを安定版スリム Linux で使用する場合 (
Debian 9 "Stretch"
今のところ)。-
使用
debian:stretch-slim
(最新の安定版)ベースイメージ -
使用 Dockerの多段ビルド
-
最初のDockerビルドステージ。
-
ダウンロードとインストール
Oracle OpenJDK
アーカイブを最初のDockerビルドステージにインストールします。 -
を使用して、プロジェクト用の最小限のJavaディストリビューション(別名JRE)をコンパイルします。
jlink
ツール
-
ダウンロードとインストール
-
2つ目のDockerビルドステージ。
- ステージ1から新しいイメージにコンパイルされた最小限のJavaディストリビューションをコピーします。
- Javaにアクセスするためのパスを設定します。
- アプリケーションのjarをイメージにコピーする
-
では、最終的に
Dockerfile
は次のようになります。( JDKを実現する
VERSION
,URL
とHASH
値 ):# First stage: JDK 11 with modules required for Spring Boot FROM debian:stretch-slim as packager # source JDK distribution names # update from https://jdk.java.net/java-se-ri/11 ENV JDK_VERSION="11.0.1" ENV JDK_URL="https://download.java.net/java/GA/jdk11/13/GPL/openjdk-${JDK_VERSION}_linux-x64_bin.tar.gz" ENV JDK_HASH="7a6bb980b9c91c478421f865087ad2d69086a0583aeeb9e69204785e8e97dcfd" ENV JDK_HASH_FILE="${JDK_ARJ_FILE}.sha2" ENV JDK_ARJ_FILE="openjdk-${JDK_VERSION}.tar.gz" # target JDK installation names ENV OPT="/opt" ENV JKD_DIR_NAME="jdk-${JDK_VERSION}" ENV JAVA_HOME="${OPT}/${JKD_DIR_NAME}" ENV JAVA_MINIMAL="${OPT}/java-minimal" # downlodad JDK to the local file ADD "$JDK_URL" "$JDK_ARJ_FILE" # verify downloaded file hashsum RUN { \ echo "Verify downloaded JDK file $JDK_ARJ_FILE:" && \ echo "$JDK_HASH $JDK_ARJ_FILE" > "$JDK_HASH_FILE" && \ sha256sum -c "$JDK_HASH_FILE" ; \ } # extract JDK and add to PATH RUN { \ echo "Unpack downloaded JDK to ${JAVA_HOME}/:" && \ mkdir -p "$OPT" && \ tar xf "$JDK_ARJ_FILE" -C "$OPT" ; \ } ENV PATH="$PATH:$JAVA_HOME/bin" RUN { \ java --version ; \ echo "jlink version:" && \ jlink --version ; \ } # build modules distribution RUN jlink \ --verbose \ --add-modules \ java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \ # java.naming - javax/naming/NamingException # java.desktop - java/beans/PropertyEditorSupport # java.management - javax/management/MBeanServer # java.security.jgss - org/ietf/jgss/GSSException # java.instrument - java/lang/instrument/IllegalClassFormatException --compress 2 \ --strip-debug \ --no-header-files \ --no-man-pages \ --output "$JAVA_MINIMAL" # Second stage, add only our minimal "JRE" distr and our app FROM debian:stretch-slim ENV JAVA_HOME=/opt/java-minimal ENV PATH="$PATH:$JAVA_HOME/bin" COPY --from=packager "$JAVA_HOME" "$JAVA_HOME" COPY "build/libs/spring-boot-demo.jar" "/app.jar" EXPOSE 8080 CMD [ "-jar", "/app.jar" ] ENTRYPOINT [ "java" ]
注意 :
-
最小限の JRE の例には、5 つの Java モジュールが含まれています (
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument
). 私はそれらを手動で発見し、アプリケーションを実行し、修正しました。ClassNotFoundException
. どのJavaモジュールをいつインクルードするか、また、以下のような冗長な依存関係を削除するのと同様に、Spring Boot開発者の推奨/ガイドを待っている。java.desktop
のみに使用されているようです。PropertyEditorSupport
-
これらのモジュールは非常に軽量で、すべて合わせると約 2 MB のサイズアップになります。の完全なリストを取得します。
java.*
とjdk.*
11 のモジュールです。java --list-modules | grep -E "^java\.[^@]*" | cut -d @ -f 1
java --list-modules | grep -E "^jdk\.[^@]*" | cut -d @ -f 1
私の場合、結果の画像サイズは 123 MB で、最小限の7つのSpring Bootモジュールと 125 MB で、すべての
java.*
モジュールこのビルドワークフローのオプションの改善として :
- ダウンロードしたJDKを展開したイメージをプリビルドし、第一段階のベースイメージとして使用する。
- 毎回インクルードするモジュールがわかっている場合、最小限の JRE とインクルードモジュールをコンパイルしたベースイメージをプリビルドします。
-
使用
-
簡単な方法 ベンダーの Open JDK ディストリビューション :
オラクルとは逆 AzulのZulu JDK 11 サポート アルパイン・ポート をサポートし、それぞれのベースとなる Dockerイメージ .
このように、Zulu JVM/JDKを尊重すれば、Dockerのビルドはよりシンプルになります。
FROM azul/zulu-openjdk-alpine:11 as packager
RUN { \
java --version ; \
echo "jlink version:" && \
jlink --version ; \
}
ENV JAVA_MINIMAL=/opt/jre
# build modules distribution
RUN jlink \
--verbose \
--add-modules \
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
# java.naming - javax/naming/NamingException
# java.desktop - java/beans/PropertyEditorSupport
# java.management - javax/management/MBeanServer
# java.security.jgss - org/ietf/jgss/GSSException
# java.instrument - java/lang/instrument/IllegalClassFormatException
--compress 2 \
--strip-debug \
--no-header-files \
--no-man-pages \
--output "$JAVA_MINIMAL"
# Second stage, add only our minimal "JRE" distr and our app
FROM alpine
ENV JAVA_MINIMAL=/opt/jre
ENV PATH="$PATH:$JAVA_MINIMAL/bin"
COPY --from=packager "$JAVA_MINIMAL" "$JAVA_MINIMAL"
COPY "build/libs/spring-boot-demo.jar" "/app.jar"
EXPOSE 8080
CMD [ "-jar", "/app.jar" ]
ENTRYPOINT [ "java" ]
出来上がった画像は 73 MB で、さすがにアルパインディストリビューションを剥がしただけのことはあります。
関連
-
SLF4J: クラス・パスに複数のSLF4Jバインディングが含まれています。
-
Java appears タイプEを囲むインスタンスがアクセスできない。
-
Java Runtime Environmentを継続するためのメモリが不足しています。
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Docker Dockerコンテナからホストへのファイルコピー
-
[解決済み] ホストからDockerコンテナにファイルをコピーする方法は?
-
[解決済み】Dockerは仮想マシンとどう違うの?
-
[解決済み] Java 11のベースDockerイメージはなぜこんなに大きいのですか?(openjdk:11-jre-slim)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Git Pull Failed マージされていないファイルがあるため、Pull できません。
-
Jsoup-Crawlingの動作
-
セミコロン期待値エラー解決
-
keytool error: java.io.FileNotFoundException: cacerts (アクセス拒否されました。)
-
X11 DISPLAY変数が設定されていない」問題の解決方法
-
コンストラクタDate()が未定義である問題
-
IDEAError:javaの依存性エラー。Annotation processing is not supported for module cycles...(アノテーション処理はモジュールサイクルではサポートされていません。
-
ApiModel と @ApiModelProperty の使用法
-
swagger2 モデルが表示されない モデルが見つからない @ApiModel アノテーションが表示されない問題
-
[解決済み] Java 11のベースDockerイメージはなぜこんなに大きいのですか?(openjdk:11-jre-slim)