AppCDS原文はこちら。Hat).https://www.morling.dev/blog/smaller-faster-starting-container-images-with-jlink-and-appcds/数ヶ月前に、シンプルなQuarkusアプリケーションを使いながら、アプリケーションクラスデータ共有(AppCDS)を使用してJavaアプリケーションの起動時間を高速化する方法について書きました。Javahttps://quarkus.io/quarkus.package.create-appcdshttps://quarkus.io/guides/maven-tooling#quarkus-package-pkg-package-config_quarkus.package.create-appcdsそれ以来、この分野ではかなりの進歩がありました。1.6では、AppCDSのビルトインサポートが導入され、プロジェクトをビルドする際に-Dquarkus.package.create-appcds=trueオプションを指定するだけで、ターゲットフォルダ内にAppCDSファイルが見つかります。9で追加されたjlinkツールを使用して作成されたカスタムJavaランタイムイメージとAppCDSを組み合わせる場合、物事はより難しくなります。jlinkhttps://docs.oracle.com/javase/jp/15/docs/specs/man/jlink.htmlhttps://docs.oracle.com/en/java/javase/15/docs/specs/man/jlink.html特にLinuxコンテナを使ったJavaアプリケーションのデプロイメントについて考えた場合、カスタムランタイムイメージとAppCDSの組み合わせは非常に魅力的です。モジュールのみを追加します。アーカイブを追加するために使用することができます。クラスタ内のワーカーノードへの配布などが高速になり、起動も大幅に速くなります。ランタイムと全く同じもので作成されなければならないという課題があります。アーカイブを生成するために使用されなければならないことを意味します。言い換えれば、Quarkusビルドが生成するデフォルトのアーカイブは、残念ながらjlinkイメージでは使用できません。この記事の目的は以下の通りです。CRUDアプリケーション用のカスタムランタイムイメージを作成するために必要な手順を説明します。AppCDShttps://github.com/gunnarmorling/quarkus-cdsこのカスタムランタイムイメージとアプリケーション自体を使ってLinuxコンテナイメージを構築する方法を紹介します。このアプローチが、フルJavaランタイムを使用したコンテナイメージと比較して、サイズと起動時間の点で比較します。恩恵を受けることができるというのは、よくある誤解です。Ritterが以下のエントリで説明しているように、実際にはそうではありません。カスタムランタイムイメージを使ってアプリケーションを実行する上で、アプリケーションを完全にモジュール化する必要はありません。Applicationshttps://medium.com/azulsystems/using-jlink-to-build-java-runtimes-for-non-modular-applications-9568c5e70ef4確かに、適切なJavaモジュールだけで構成されていればランタイムイメージの作成は少し簡単ですが、明示的にどのJDK(または他の)モジュールを含むべきか指定すれば、ランタイムイメージの作成自体は可能です。ランタイムで実行するのと同じように、従来のクラスパスを使って実行できます。どのJDKモジュールを追加すればいいのでしょうか?この質問に答えるには、jdepsツールが便利です。jdepshttps://docs.oracle.com/javase/jp/15/docs/specs/man/jdeps.htmlhttps://docs.oracle.com/en/java/javase/15/docs/specs/man/jdeps.htmlその--print-module-depsオプションを使うと、与えられたJARのセットに対して、どの(JDK)モジュールに依存しているのか、そしてカスタムランタイムイメージに入れる必要があるのはどれなのかを判断することができます。verifyでビルドしたので、以下のようにjdepsを起動してみましょう。target/todo-manager-1.0.0-SNAPSHOT-runner.jarですが、結果はエラーになりました...。setなるほど、マルチリリースJAR向けにどのコードバージョンを解析するかを知らせる必要がありますね。target/todo-manager-1.0.0-SNAPSHOT-runner.jarちょっと進展しましたが、まだ問題がありますね。java.ws.rsこれはちょっとおかしいですね。org.jboss.spec.javax.ws.rs.jboss-jaxrs-api_2.1_spec-2.0.1.Final.jarというファイルは、module-info.class記述子を持つ明示的なモジュールで、モジュールjava.xml.bindを参照しているのですが、これはモジュールパスにはありません。JARはクラスパスの一部であり、モジュールパスではないことを考えると、なぜこれがここでフラグが立てられるのか、私にはよくわかりません。それは大きな問題ではありません。API(これもクラスパスで提供されています)を単にモジュールパスに追加すればよいのです。明示的なモジュールである他のいくつかの依存関係についても同じ問題が発生するため、以下のような設定になってしまいました。target/todo-manager-1.0.0-SNAPSHOT-runner.jar別の問題は、欠落した依存関係です。found...よく見てみると、これらはコンパイル時のみの依存関係(Checkerフレームワークのアノテーションのようなもの)、もしくは今回のケースには関係のないオプション機能の依存関係のいずれかです。スイッチを使って、jpdesの呼出しをしつつも安全に無視できます。target/todo-manager-1.0.0-SNAPSHOT-runner.jar必要なJDKモジュールが最終的に表示されます。15を構成するおよそ60個のモジュールから、このアプリケーションで必要なのはたった10個ということです。これらのモジュールのみを含むカスタムランタイムイメージを作ればかなりのスペース節約になります。Required?モジュールリストを見ると、なんでこのモジュールが実際に必要なのか、と思うことでしょう。jdk.jconsoleを使ってこのアプリケーションは何をやっているのでしょうか。この詳細を知る場合においても、jdepsが役に立ちます。スイッチを付けずに再度jdepsを実行すると、興味深いモジュール参照をgrepできます。依存関係が一つあります。詳細に依存しますが、そのようなライブラリのメンテナに連絡して、この依存関係が本当に必要なのか、それとも(問題のコードを別のモジュールに移動させるなどして)回避できるのかを議論するのもよいでしょう。結果としてカスタムランタイムイメージのサイズがさらに小さくなる可能性があります。必要なモジュールのリストを使えば、実際のランタイムイメージの生成はとても簡単です。ランタイムを圧縮するだけでなく、ヘッダーファイルやmanページの省略により、さらにランタイムイメージのサイズを小さくできます。アーカイブを作成するために、イメージ自体のすべてのクラスのクラスデータアーカイブを追加する必要があります。これに失敗すると、このようなエラーメッセージが表示されます。loadedこの手順はあまり文書による説明がないので、この時点でちょっと進みが遅くなってしまいました。いつものことながらOpenJDKコミュニティを頼ることができます。Redestadが方向性を示してくれました。-Xshare:dumpありがとう、Claes!このおかげで、ベースクラスのデータアーカイブをtarget/runtime-image/lib/server/classes.jsaに作成できました。ランタイムイメージは12MBほど増えたとはいえ、現時点で63MBほどなので、悪くないですね。ImageカスタムJavaランタイムイメージを作成したので、そこにAppCDSアーカイブを追加してみましょう。13では動的なAppCDSアーカイブが導入されているので、-XX:ArchiveClassesAtExitオプションを指定してアプリケーションを実行するだけの簡単なステップです。後でアプリケーションを実行する際に使われるクラスパスは、AppCDSアーカイブビルド時に使われるクラスパスと同一でなければなりません(正確に言えばクラスパスの接頭辞が同一である必要がある)。*-runner.jarを使って実行する必要があります。ランタイムイメージのjavaバイナリを使ってアプリケーションを起動し、アプリケーション終了時にAppCDSアーカイブを作成します。これにより、target/runtime-image/cds/app-cds.jsaにCDSアーカイブが作成されます。コンテナイメージにこのアーカイブを追加できます。場合はそうではないことに注意してください。上でビルドする必要があります。自分自身がLinux上で実行しておらず、WindowsやmacOS上で実行している場合は、ビルドプロセス全体をコンテナにしてしまえば、この目的を達成できます。Dockerfile:この時点で、実際のアプリケーション、必要なJDKモジュールが入ったカスタムJavaランタイムイメージ、アプリケーションクラスのAppCDSアーカイブができました。最後のステップはこれら全てをLinuxコンテナイメージに入れることです。これは小さなDockerfileで速やかに実施できます。]ここではFedoraのminimalベースイメージを使っていますが、このイメージはコンテナイメージ用のよいベースイメージです。ディストリビューションの柔軟性を提供しています。必要に応じてツールを追加できます。CとPOSIX標準APIの実装として、Alpineは(JDKで使用されている)glibcの代わりにmuslが付属していることです。移植版を提供することを目的としています。15の時点では、この移植版のGAビルドはまだ存在しません。16では、Alpine/musl対応の早期アクセスビルドが利用可能です。Buildhttps://jdk.java.net/16/コンテナイメージを小さくするためのもう一つのオプションとして、jibの利用がありますが、これもQuarkusでサポートされています(jibがカスタムランタイムイメージとAppCDSでどのように動作するのかをまだ試してはいません)。jibhttps://github.com/GoogleContainerTools/jibJibhttps://quarkus.io/guides/container-image#jibまた、ベースイメージのサイズは、実際にはあまり気にならないということも指摘しておきましょう。コンテナイメージはレイヤー化されたファイルシステムを使用しているため、コンテナイメージをPushしたりPullしたりする際に、通常は安定したベースイメージレイヤーの再配布が不要なのです。コンテナのエントリポイントであるtodo-manager.shは、基本的なシェルスクリプトで、実際のJavaアプリケーションをJavaランタイムイメージを使って開始します。itアーカイブ名を指定する。Numbers!最後に、数値を比較してみましょう。ToDo管理アプリケーションを様々な方法でコンテナ化した場合の、コンテナイメージのサイズと起動時間です。今回は4つの異なるアプローチを試してみました。RAM)で実行した結果です。Cloudhttps://www.hetzner.com/cloudご覧のように、JDKフルサイズではなくカスタムJavaランタイムイメージを追加すると、コンテナイメージのサイズが大幅に小さくなります。33のOpenJDKパッケージと比較すると、その差は顕著です。起動時間はQuarkusで表示されている通りで、5回の実行で平均したものです。341)でのJDKクラスのデフォルトCDSアーカイブの導入によるものです。Archiveshttp://openjdk.java.net/jeps/341カスタムランタイムイメージを使用すること自体は、起動時間に測定可能な影響は与えていません。AppCDSアーカイブは起動時間を54%も改善しました。それだけの価値があると言えるでしょう。追加した場合よりもはるかに小さいです。使って作成したカスタムJavaランタイムイメージとAppCDSアーカイブの組み合わせは、コンテナ化されたJavaアプリケーションのための素晴らしい基盤になると言っても良いと思います。アプリケーションが実際に必要とするJDKモジュールのみを含むカスタムランタイムイメージを追加することで、イメージサイズを大幅に削減できます。節約したスペースの一部はAppCDSアーカイブの追加に割けるので、最終的には、より小さく、より速く起動するコンテナイメージが得られます。1つの欠点は、ランタイムイメージとAppCDSアーカイブを生成するためのビルドプロセスが複雑になることです。Mavenプラグインのようなツールやその他のツールがこの点をさらに改善してくれることを期待しています。厄介な点として、必要なJDKモジュールのセットに影響を与える依存関係をアプリケーションに追加した場合、カスタムランタイムイメージを再構築することを忘れてはいけないということです。ランタイムイメージを使って実行しているアプリケーションの自動テストは、この状況を特定するのに役立つはずです。ご自身で試してみたい方や、ご自身のハードウェア上での異なるデプロイ方法の数値を取得したい方は、以下のGitHubリポジトリに必要なコードと情報をすべて掲載しています。コメントをキャンセルコメントを入力してください。以下に詳細を記入するか、アイコンをクリックしてログインしてください。アカウントを使ってコメントしています。アカウントを使ってコメントしています。新しいコメントがついたらメールで通知。Inside現在40人フォロワーがいます。購読管理このバーを折りたたむ%d人のブロガーが「いいね」をつけました。