ネイティブ実行可能ファイルのビルド
このガイドでは以下をカバーしています。
-
アプリケーションをネイティブ実行可能ファイルにコンパイル
-
ネイティブ実行可能ファイルのコンテナーへのパッケージング
-
ネイティブ実行可能ファイルのデバッグ
このガイドは、入門ガイド で開発されたアプリケーションを入力としています。
要件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
動作するコンテナランタイム(Docker, Podman)
-
使用したい場合は、 Quarkus CLI
-
MandrelまたはGraalVMがインストールされ、 適切に設定されていること
-
入門ガイド で開発したアプリケーションのコード。
C言語でのネイティブコンパイルのサポート
動作するC言語の開発環境があるとはどういう意味でしょうか?
|
背景
ネイティブな実行可能ファイルをビルドするには、GraalVM のディストリビューションを使用する必要があります。ディストリビューションは3つあります。 Oracle GraalVM Community Edition (CE)、Oracle GraalVM Enterprise Edition (EE)、そして Mandrel です。Oracle ディストリビューションと Mandrel ディストリビューションの違いは以下の通りです。
-
Mandrelは、Oracle GraalVM CEのダウンストリームディストリビューションです。Mandrelの主な目的は、Quarkusをサポートするために特別に設計されたネイティブ実行可能ファイルを構築する方法を提供することです。
-
Mandrel のリリースは、アップストリームのOracle GraalVM CEコードベースから派生したコードベースから構築されており、わずかな変更しか行われていませんが、Quarkusネイティブアプリには必要ない重要な除外事項がいくつかあります。これらのリリースは、Oracle GraalVM CEと同じ機能をサポートしており、機能に大きな変更はありません。特筆すべきは、多言語プログラミングのサポートが含まれていないことです。これらの除外の理由は、大多数のQuarkusユーザーにより良いレベルのサポートを提供するためです。また、これらの除外は、Oracle GraalVM CE/EEと比較して、Mandrelの配布サイズが大幅に縮小されていることを意味しています。
-
Mandrelは、標準のOpenJDKプロジェクトを使用して、Oracle GraalVM CEとは少し違った形で構築されています。これは、Oracleが独自のGraalVMダウンロードを構築するために使用するOpenJDKのバージョンに追加したいくつかの小さな機能強化から利益を得られないことを意味します。アップストリームのOpenJDKはそれらを管理しておらず、保証することができないため、このような機能強化は省略されています。これは、規格適合性とセキュリティーに関しては特に重要です。
-
Mandrel は現在のところ、Linux のコンテナー化された環境をターゲットとしたネイティブ実行可能ファイルのビルドにのみ推奨されています。つまり、Mandrel ユーザーは、コンテナーを使用してネイティブ実行可能ファイルを構築することが推奨されます。macOS 用のネイティブ実行可能ファイルをビルドする場合、Mandrel は現在そのプラットフォームをターゲットにしていないため、代わりに Oracle GraalVM の使用を検討するべきです。ベアメタルの Linux 上で直接ネイティブ実行可能ファイルをビルドすることも可能です。詳細は Mandrel READMEおよび Mandrel のリリース を参照してください。
GraalVMの設定
このステップは、Linux 以外のオペレーティングシステムをターゲットとしたネイティブ実行可能ファイルを生成する場合にのみ必要です。 Linux をターゲットとしたネイティブ実行可能ファイルを生成する場合は、このセクションを省略して代わりに use a builder image。 |
GraalVM をインストールできない場合は、マルチステージの Docker ビルドを使用して、GraalVM が組み込まれた Docker コンテナー内で Maven を実行できます。 これを行う方法については、the end of this guide で説明しています。 |
GraalVM for JDK 21 が必要です。
-
まだの場合は、GraalVM をインストールします。これにはいくつかのオプションがあります:
-
https://github.com/graalvm/mandrel/releases または https://github.com/graalvm/graalvm-ce-builds/releases から適切なアーカイブをダウンロードし、他の JDK と同じように展開します。
-
sdkman、 homebrew、 scoop などのプラットフォーム固有のインストーラーツールを使用します。 GraalVM の コミュニティーエディション が推奨されます。たとえば、
sdk install java 21-graalce
でインストールします。
-
-
ランタイム環境を構成します。
GRAALVM_HOME
環境変数をGraalVMインストールディレクトリに設定します。例えば:export GRAALVM_HOME=$HOME/Development/mandrel/
macOS (Mandrel ではサポート対象外) では、変数を
Home
のサブディレクトリに指定します:export GRAALVM_HOME=$HOME/Development/graalvm/Contents/Home/
Windowsでは、コントロールパネルから環境変数を設定する必要があります。
scoop でインストールすれば自動的に設定されます。
-
(オプション) 環境変数
JAVA_HOME
を GraalVM のインストールディレクトリに設定します。export JAVA_HOME=${GRAALVM_HOME}
-
(オプション) GraalVM
bin
ディレクトリをパスに追加しますexport PATH=${GRAALVM_HOME}/bin:$PATH
macOS で GraalVM を使用する場合の問題
この GraalVM の問題 で報告されているように、GraalVM バイナリーは (まだ) macOS に対して認証されていません。つまり、
回避策として、次のコマンドを使用して、GraalVMインストールディレクトリ上の
|
ソリューション
次のセクションの手順に従って、アプリケーションを段階的にパッケージ化することをお勧めします。しかしながら、完成したサンプルに直接進むこともできます。
git clone https://github.com/quarkusio/quarkus-quickstarts.git
で Git リポジトリーをクローンします。または、https://github.com/quarkusio/quarkus-quickstarts/archive/main.zip[アーカイブ] をダウンロードします。
ソリューションは getting-started
ディレクトリに存在します。
ネイティブ実行可能ファイルの生成
アプリケーションのネイティブ実行可能ファイルには、アプリケーション・コード、必要なライブラリ、Java API、および VM の縮小版が含まれます。VM ベースが小さくなることで、アプリケーションの起動時間が改善され、ディスクフットプリントが最小限に抑えられます。
前回のチュートリアルでアプリケーションを生成した場合は、 pom.xml
に以下の Maven プロファイルセクションがあります。
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<properties>
<skipITs>false</skipITs>
<quarkus.native.enabled>true</quarkus.native.enabled>
</properties>
</profile>
</profiles>
もう一つの可能性は、 ネイティブイメージ構築プロセスの設定方法の詳細は、以下の ネイティブ実行可能ファイルの設定 セクション参照してください。 |
すぐにわかると思いますが、ネイティブ実行可能ファイルのパッケージ化には 数分 かかるため、プロファイルを使用しています。 コマンドラインでプロパティーとして -Dquarkus.native.enabled=true を渡すこともできますが、プロファイルを使用するとネイティブイメージテストも実行できるようになるため、プロファイルを使用することをお勧めします。
次のようにネイティブ実行可能ファイルの作成します:
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true
Windows でのパッケージ化に関する問題
Visual Studio の Microsoft Native Tools はパッケージ化する前に初期化する必要があります。
これは、Visual Studio ビルドツールと一緒にインストールされた もう一つのソリューションは、これを行うためのスクリプトを書くことです:
|
通常のファイルに加えて、このビルドでは target/getting-started-1.0.0-SNAPSHOT-runner
を生成します。これを実行するには、次のようにします: ./target/getting-started-1.0.0-SNAPSHOT-runner
.
Java プレビュー機能
プレビュー機能に依存する Java コードには、特別な注意が必要です。これは、ネイティブ実行可能ファイルを生成する場合、 |
完全に静的なネイティブ実行可能ファイルの作成
完全に静的なネイティブ実行可能ファイルのサポートは実験的なものです。 |
Linux では、システムの共有ライブラリに依存しないネイティブ実行可能ファイルをパッケー ジ化できます。
満たすべき いくつかのシステム要件 と、 native-image
の呼び出しとともに使用する追加のビルド引数がありますが、最低限必要なのは -Dquarkus.native.additional-build-args="--static","--libc=musl"
です。
完全な静的バイナリのコンパイルは、 glibc
の代わりに musl を静的にリンクすることで行われます。厳密なテストなしに実運用で使用するべきではありません。
ネイティブ実行可能ファイルのテスト
ネイティブ実行可能ファイルを生成することはいくつかの問題を引き起こす可能性があるので、ネイティブファイルで実行されているアプリケーションに対していくつかのテストを実行することをお勧めします。その理由は テストのガイド で説明されています。
GreetingResourceIT
がネイティブ実行可能ファイルに対して実行されることを確認するには、 ./mvnw verify -Pnative
を使用します。
$ ./mvnw verify -Dnative
...
Finished generating 'getting-started-1.0.0-SNAPSHOT-runner' in 22.0s.
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] docker run --env LANG=C --rm --user 1000:1000 -v /home/zakkak/code/quarkus-quickstarts/getting-started/target/getting-started-1.0.0-SNAPSHOT-native-image-source-jar:/project:z --entrypoint /bin/bash quay.io/quarkus/ubi9-quarkus-mandrel-builder-image:jdk-21 -c objcopy --strip-debug getting-started-1.0.0-SNAPSHOT-runner
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 70686ms
[INFO]
[INFO] --- maven-failsafe-plugin:3.0.0-M7:integration-test (default) @ getting-started ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running org.acme.getting.started.GreetingResourceIT
Executing "/home/zakkak/code/quarkus-quickstarts/getting-started/target/getting-started-1.0.0-SNAPSHOT-runner -Dquarkus.http.port=8081 -Dquarkus.http.ssl-port=8444 -Dtest.url=http://localhost:8081 -Dquarkus.log.file.path=/home/zakkak/code/quarkus-quickstarts/getting-started/target/quarkus.log -Dquarkus.log.file.enable=true -Dquarkus.log.category."io.quarkus".level=INFO"
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-05-05 10:55:52,068 INFO [io.quarkus] (main) getting-started 1.0.0-SNAPSHOT native (powered by Quarkus 3.0.2.Final) started in 0.009s. Listening on: http://0.0.0.0:8081
2023-05-05 10:55:52,069 INFO [io.quarkus] (main) Profile prod activated.
2023-05-05 10:55:52,069 INFO [io.quarkus] (main) Installed features: [cdi, rest, smallrye-context-propagation, vertx]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.99 s - in org.acme.getting.started.GreetingResourceIT
...
Quarkus では、デフォルトでネイティブイメージの起動を 60 秒間待機した後、自動的にネイティブテストが失敗します。
この時間は、 |
この手順は、以前は |
プロファイル
デフォルトでは、インテグレーションテストは prod
プロファイルを使用して、ネイティブ実行可能ファイルに対して build と run の両方を行います。
quarkus.test.native-image-profile
プロパティを使用して、テスト中に実行可能ファイルが 実行 されるプロファイルをオーバーライドできます。
application.properties
に追加するか、次のようにコマンドラインに追加してください:
./mvnw verify -Dnative -Dquarkus.test.native-image-profile=test
。
接頭辞 %test.
が付いたプロパティーは、テスト実行時に使用されます。
quarkus-profile=test
プロパティーを使用すると、実行可能ファイルが ビルド されて 実行さ れるプロファイルをオーバーライドできます
(例: ./mvnw clean verify -Dnative -Dquarkus.profile=test
)。これは、データベースへのテストデータのインポートなど、テスト固有のリソースを処理する場合に便利です。
quarkus.native.resources.includes=version.txt
%test.quarkus.native.resources.includes=version.txt,import-dev.sql
%test.quarkus.hibernate-orm.database.generation=drop-and-create
%test.quarkus.hibernate-orm.sql-load-script=import-dev.sql
上記の例を application.properties
に記述すると、Hibernate ORM が管理するデータベースには、JVM モードのテスト実行中とネイティブモードのテスト実行中の両方でテストデータが入力されることになります。本番用の実行ファイルには version.txt
リソースのみが含まれ、余分なテストデータは含まれません。
または、ネイティブ実行可能ファイルに対してテストを実行するときに、
|
Java プレビュー機能
Java プレビュー機能
プレビュー機能に依存する Java コードには、特別な注意が必要です。
ネイティブ実行可能ファイルをテストする場合は、 |
ネイティブ実行可能ファイルとして実行している場合のテストの除外
この方法でテストを実行する場合、実際にネイティブで実行されるのはアプリケーションのエンドポイントのみで、HTTP 呼び出しでしかテストできません。テストコードは実際にはネイティブには実行されないので、HTTP エンドポイントを呼び出さないコードをテストしている場合は、それらをネイティブテストの一部として実行するのは良い考えではないでしょう。
上記のようにJVMとネイティブ実行でテストクラスを共有している場合、特定のテストをネイティブイメージに対してテストをするときに、 @DisabledOnNativeImage
アノテーションを付けてそれらをスキップできます。
|
既存のネイティブ実行可能ファイルのテスト
すでにビルドされているネイティブ実行可能ファイルに対してテストを再実行することも可能です。
その場合は ./mvnw test-compile failsafe:integration-test
を実行します。これにより、既存のネイティブイメージが検出され、フェイルセーフを使用してそれに対してテストが実行されます。
何らかの理由でプロセスがネイティブイメージを見つけられない場合や、ターゲットディレクトリーにないネイティブイメージをテストしたい場合は、 -Dnative.image.path=
システムプロパティーで実行ファイルを指定することができます。
GraalVM をインストールせずに Linux 実行可能ファイルを作成する方法
先に進む前に、コンテナーランタイム(Docker、podman)の動作環境が整っていることを確認しておきましょう。WindowsでDockerを使用している場合は、Docker Desktopのファイル共有設定でプロジェクトのドライブを共有し、Docker Desktopを再起動する必要があります。 |
多くの場合、Quarkusアプリケーション用のネイティブLinux実行ファイルを作成する必要があります(例えば、コンテナー化された環境で実行するためなど)、このタスクを達成するために適切なGraalVMバージョンをインストールする手間を省きたいと考えています(例えば、CI環境では、できるだけ少ないソフトウェアをインストールするのが一般的です)。
このため、Quarkusでは、Dockerやpodmanなどのコンテナーランタイムを利用して、ネイティブのLinux実行ファイルを作成する非常に便利な方法を提供しています。このタスクを達成する最も簡単な方法は、次を実行することです:
quarkus build --native --no-tests -Dquarkus.native.container-build=true
# The --no-tests flag is required only on Windows and macOS.
./mvnw install -Dnative -DskipTests -Dquarkus.native.container-build=true
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true
デフォルトでは、Quarkus はコンテナーランタイムを自動的に検出します。 コンテナーランタイムを明示的に選択したい場合は、次のようにします: Docker の場合: CLI
Maven
Gradle
podman の場合: CLI
Maven
Gradle
これらは通常の Quarkus 設定プロパティーであるため、常にコンテナーでビルドしたい場合は、
毎回指定しなくて済むように |
コンテナ・ランタイムを使用してこの方法でビルドされた実行可能ファイルは、64ビットLinux実行可能ファイルとなるため、オペレーティング・システムによっては実行できなくなる可能性があります。
Quarkus 3.19以降では、ネイティブ実行可能ファイルのビルドに使用される ビルダー イメージはUBI 9に基づいています。つまり、コンテナのビルドによって生成されるネイティブ実行可能ファイルもUBI 9に基づいています。したがって、コンテナのビルドを計画している場合は、
UBI8で使用可能なタグは こちら 、UBI9で使用可能なタグは こちら(UBI 9) ) |
JARが正常にビルドされているにもかかわらず、コンテナービルドでネイティブ実行可能ファイルを作成しようとすると、アプリケーションJARに対して以下のようなinvalid pathエラーが表示される場合は、コンテナーランタイムにリモートデーモンを使用している可能性があります。 Error: Invalid Path entry getting-started-1.0.0-SNAPSHOT-runner.jar Caused by: java.nio.file.NoSuchFileException: /project/getting-started-1.0.0-SNAPSHOT-runner.jar この場合、パラメータ その理由は、 |
Mandrel の代わりに GraalVM を使用してビルドする場合は、カスタムビルダーイメージパラメーターを追加で渡す必要があります。 CLI
Maven
Gradle
|
コンテナーの作成
コンテナーイメージのエクステンションの使用
Quarkusアプリケーションからコンテナーイメージを作成する最も簡単な方法は、コンテナーイメージ エクステンションの1つを利用することです。
これらのエクステンションのいずれかが存在する場合、ネイティブ実行可能ファイル用のコンテナーイメージを作成することは、基本的には単一のコマンドを実行することになります:
./mvnw package -Dnative -Dquarkus.native.container-build=true -Dquarkus.container-image.build=true
-
quarkus.native.container-build=true
では GraalVM がインストールされていなくても Linux の実行可能ファイルを作成することができます(ローカルに GraalVM がインストールされていない場合や、ローカルのオペレーティングシステムが Linux ではない場合にのみ必要です)。
リモートDockerデーモンを実行している場合、 詳細は、Creating a Linux executable without GraalVM installed を参照してください。 |
-
quarkus.container-image.build=true
最終的なアプリケーションアーティファクト(この場合はネイティブ実行可能ファイル)を使用してコンテナーイメージを作成するようにQuarkusに指示します。
詳細については、 コンテナーイメージガイド を参照してください。
マイクロベースイメージを手動で使用する方法
Quarkus Mavenプラグインで生成されたJARを使用して、コンテナー内でアプリケーションを実行することができます。ただし、このセクションでは、生成されたネイティブ実行可能ファイルを使用してコンテナーイメージを作成することに焦点を当てます。
ローカルの GraalVM インストール環境を使用する場合、ネイティブ実行可能ファイルは、ローカルのオペレーティングシステム (Linux、macOS、Windows など) をターゲットにします。 しかし、コンテナーはオペレーティングシステムによって生成されたものと同じ 実行可能ファイル 形式を使用しない場合があるため、 (this section セクションで説明されているように) コンテナーランタイムを活用して実行可能ファイルを生成するように Maven ビルドに指示します。
生成される実行ファイルは 64 ビットの Linux 実行ファイルになるので、お使いの OS によっては実行できなくなる可能性があります。しかし、コンテナーにコピーするので問題ありません。プロジェクト生成では、 src/main/docker
ディレクトリに Dockerfile.native-micro
を用意し、以下のような内容にしています:
FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0
WORKDIR /work/
RUN chown 1001 /work \
&& chmod "g+rwX" /work \
&& chown 1001:root /work
COPY --chown=1001:root --chmod=755 target/*-runner /work/application
EXPOSE 8080
USER 1001
ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
Quarkus マイクロイメージとは?
Quarkus Micro Imageは、ネイティブアプリケーションを実行するための依存関係を提供する小さなコンテナイメージです。 UBI Micro がベースになっています。 このベースイメージは、コンテナで完全に動作するように調整されています。 UBI イメージの詳細については、以下をご覧ください: UBI イメージは制限なく使用できます。 このページ では、アプリケーションに特定の要件がある場合に、 |
あとは、生成されたネイティブ実行可能ファイルを削除していなければ、dockerイメージを使ってビルドします:
docker build -f src/main/docker/Dockerfile.native-micro -t quarkus-quickstart/getting-started .
そして最後に、以下を実行します:
docker run -i --rm -p 8080:8080 quarkus-quickstart/getting-started
最小限のベースイメージを手動で使用する方法
プロジェクト生成では、以下の内容の src/main/docker docker
ディレクトリも提供されます:
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.5
WORKDIR /work/
RUN chown 1001 /work \
&& chmod "g+rwX" /work \
&& chown 1001:root /work
COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
EXPOSE 8080
USER 1001
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
UBI の最小イメージは、上記のマイクロイメージよりも大きくなっています。これには、 microdnf
パッケージマネージャーなどのユーティリティーが含まれています。
マルチステージDockerビルドの使用
前のセクションでは、Maven または Gradle を使用してネイティブ実行可能ファイルをビルドする方法を示しましたが、その場合は最初にネイティブ実行可能ファイルを作成しておく必要があります。さらに、このネイティブ実行可能ファイルは Linux64 ビットの実行可能ファイルである必要があります。
ビルドツールを含む最終的なコンテナーを用意せずに、ネイティブ実行可能ファイルをコンテナーに直接ビルドする必要がある場合もあるはずです。このアプローチは、マルチステージの Docker ビルドで使用可能です:
-
最初の段階では、Maven または Gradle を使用してネイティブ実行可能ファイルをビルドします
-
第 2 段階は、生成されたネイティブ実行可能ファイルをコピーする最小限のイメージです
以下のDockerファイルからコンテナーイメージをビルドする前に、デフォルトの |
このような多段階を用いたビルドは、次のように実現できます:
MavenでビルドするためのサンプルDockerfileです:
## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi9-quarkus-mandrel-builder-image:jdk-21 AS build
COPY --chown=quarkus:quarkus --chmod=0755 mvnw /code/mvnw
COPY --chown=quarkus:quarkus .mvn /code/.mvn
COPY --chown=quarkus:quarkus pom.xml /code/
USER quarkus
WORKDIR /code
RUN ./mvnw -B org.apache.maven.plugins:maven-dependency-plugin:3.8.1:go-offline
COPY src /code/src
RUN ./mvnw package -Dnative
## Stage 2 : create the docker final image
FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0
WORKDIR /work/
COPY --from=build /code/target/*-runner /work/application
# set up permissions for user `1001`
RUN chmod 775 /work /work/application \
&& chown -R 1001 /work \
&& chmod -R "g+rwX" /work \
&& chown -R 1001:root /work
EXPOSE 8080
USER 1001
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
このマルチステージ Docker ビルドは、ホストマシンから Maven ラッパーをコピーします。
Maven ラッパー (または Gradle ラッパー) は、特定のバージョンの Maven/Gradle を提供するための便利な方法です。
これにより、Maven と Gradle を使用してベースイメージを作成する必要がなくなります。
プロジェクトで Maven ラッパーをプロビジョニングするには、 mvn wrapper:wrapper を使用します。
|
このファイルは、Getting started quickstartには含まれていないので、 src/main/docker/Dockerfile.multistage
に保存してください。
GradleでビルドするためのサンプルDockerfileです:
## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi9-quarkus-mandrel-builder-image:jdk-21 AS build
USER root
RUN microdnf install findutils -y
COPY --chown=quarkus:quarkus gradlew /code/gradlew
COPY --chown=quarkus:quarkus gradle /code/gradle
COPY --chown=quarkus:quarkus build.gradle /code/
COPY --chown=quarkus:quarkus settings.gradle /code/
COPY --chown=quarkus:quarkus gradle.properties /code/
USER quarkus
WORKDIR /code
COPY src /code/src
RUN ./gradlew build -Dquarkus.native.enabled=true
## Stage 2 : create the docker final image
FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0
WORKDIR /work/
COPY --from=build /code/build/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
プロジェクトでGradleを使用している場合は、このサンプルDockerfileを使用することができます。 src/main/docker/Dockerfile.multistage
に保存してください。
docker build -f src/main/docker/Dockerfile.multistage -t quarkus-quickstart/getting-started .
最後に、以下を実行します:
docker run -i --rm -p 8080:8080 quarkus-quickstart/getting-started
ネイティブ実行可能ファイルにSSLサポートが必要な場合は、Dockerイメージに必要なライブラリを簡単に含めることができます。 詳しくは ネイティブ実行可能ファイルでのSSL利用ガイド を参照してください。 |
Mandrel の代わりに GraalVM CE を使用するには、 |
Distroless ベースイメージの使用
Distroless イメージのサポートは実験的なものです。 |
小さなコンテナーイメージを探している場合は、 distroless アプローチでベースレイヤーのサイズが縮小されます。 distroless の背後には、すべての要件 (場合によってはアプリケーション自体) を含む単一の最小限のベースイメージを使用するという考え方があります。
Quarkus は、 Dockerfile
で使用できる distroless ベースイメージを提供します。ユーザーは、アプリケーションをコピーするだけです:
FROM quay.io/quarkus/quarkus-distroless-image:2.0
COPY target/*-runner /application
EXPOSE 8080
USER nonroot
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
Quarkus は、 quay.io/quarkus/quarkus-distroless-image:2.0
イメージを提供します。ネイティブ実行可能ファイルを実行するために必要なパッケージが含まれており、サイズはほんの 9Mb です。このイメージの上にアプリケーションを追加するだけで、小さなコンテナーイメージを得られます。
Distroless イメージを本番環境で使用する場合は、必ず厳密なテストを実施してください。
コンテナーイメージをゼロから構築する
スクラッチベースイメージのサポートは実験的なものです。 |
完全に静的にリンクされたバイナリをビルドすることで、ビルド結果のネイティブ実行可能ファイルのみを含む スクラッチイメージ を使用することができます。
Scratch
からイメージを構築するためのサンプルのマルチステージのDockerfileです:
## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi9-quarkus-graalvmce-builder-image:jdk-21 AS build
USER root
RUN microdnf install make gcc -y
COPY --chown=quarkus:quarkus mvnw /code/mvnw
COPY --chown=quarkus:quarkus .mvn /code/.mvn
COPY --chown=quarkus:quarkus pom.xml /code/
RUN mkdir /musl && \
curl -L -o musl.tar.gz https://more.musl.cc/11.2.1/x86_64-linux-musl/x86_64-linux-musl-native.tgz && \
tar -xvzf musl.tar.gz -C /musl --strip-components 1 && \
curl -L -o zlib.tar.gz https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz && \
mkdir zlib && tar -xvzf zlib.tar.gz -C zlib --strip-components 1 && \
cd zlib && ./configure --static --prefix=/musl && \
make && make install && \
cd .. && rm -rf zlib && rm -f zlib.tar.gz && rm -f musl.tar.gz
ENV PATH="/musl/bin:${PATH}"
USER quarkus
WORKDIR /code
RUN ./mvnw -B org.apache.maven.plugins:maven-dependency-plugin:3.8.1:go-offline
COPY src /code/src
RUN ./mvnw package -Dnative -DskipTests -Dquarkus.native.additional-build-args="--static","--libc=musl"
## Stage 2 : create the final image
FROM scratch
COPY --from=build /code/target/*-runner /application
EXPOSE 8080
ENTRYPOINT [ "/application" ]
スクラッチイメージを本番環境で使用する場合は、必ず厳密なテストを実施してください。
ネイティブイメージの実行可能ファイルの要件に合わせて、muslとzlibのバージョンを更新する必要があるかもしれません(ネイティブイメージ圧縮を使用する場合はUPXも)。 |
ネイティブイメージの圧縮
Quarkus は、UPX を使用して生成されたネイティブ実行可能ファイルを圧縮できます。詳細については、UPX 圧縮のドキュメント を参照してください。
Java とネイティブイメージのコンパイルの分離
特定の状況では、別のステップでネイティブイメージをビルドする必要がある場合もあります。
たとえば、CI/CD パイプラインで、ネイティブイメージの生成に使用するソースを生成するステップと、これらのソースを使用して実際にネイティブ実行可能ファイルをビルドするステップを分けたい場合などです。
このようなユースケースでは、追加フラグとして quarkus.native.sources-only=true
を設定できます。
そうすることで、ネイティブコンパイル (-Dnative
) を開始するように Java コンパイルを実行できますが、GraalVM の native-image
の実際の呼び出しをトリガーする前に停止します。
$ ./mvnw clean package -Dnative -Dquarkus.native.sources-only=true
コンパイルが完了すると、ビルドアーティファクトが target/native-sources
に表示されます:
$ cd target/native-sources
$ ls
getting-started-1.0.0-SNAPSHOT-runner.jar graalvm.version lib native-image.args
上記の出力から、生成された jar ファイルと関連する lib ディレクトリーに加えて、 native-image.args
という名前のテキストファイルが作成されたことがわかります。
このファイルには、GraalVM の native-image
コマンドに渡すすべてのパラメーター (コンパイルする JAR の名前を含む) が保持されます。
graalvm.version
という名前のテキストファイルも作成され、使用する GraalVM のバージョンが保持されます。
GraalVM がインストールされていて、このバージョンと一致する場合は、次のコマンドを実行してネイティブコンパイルを開始できます。
$ cd target/native-sources
$ native-image $(cat native-image.args)
...
$ ls
native-image.args
getting-started-1.0.0-SNAPSHOT-runner
getting-started-1.0.0-SNAPSHOT-runner.build_artifacts.txt
getting-started-1.0.0-SNAPSHOT-runner.jar
Gradle のプロセスも同様です。
コンテナーでビルドプロセスを実行することも可能です:
$ ./mvnw clean package -Dquarkus.native.enabled=true -Dquarkus.native.sources-only=true -Dquarkus.native.container-build=true
-Dquarkus.native.container-build=true
は、ネイティブイメージのビルドに使用するDockerイメージ名を保持する native-builder.image
という名前の追加のテキストファイルを生成します。
cd target/native-sources
docker run \
-it \
--user $(id -ur):$(id -gr) \
--rm \
-v $(pwd):/work \(1)
-w /work \(2)
--entrypoint /bin/sh \
$(cat native-builder.image) \(3)
-c "native-image $(cat native-image.args) -J-Xmx4g"(4)
1 | ホストのディレクトリ target/native-image をコンテナーの /work にマウントします。したがって、生成されたバイナリーもこのディレクトリに書き込まれます。 |
2 | 作業ディレクトリーを、<1> でマウントした /work に切り替えます。 |
3 | ファイル native-builder.image からDocker イメージを使用します。 |
4 | ファイル native-image.args の内容を引数として native-image を呼び出します。また、プロセスの最大メモリーを 4 ギガバイトに制限するための追加の引数も提供します (これは、ビルドするプロジェクトとそれをビルドしているマシンにより異なります)。 |
Windows マシンで実行している場合は、バイナリーが Linux docker コンテナー内で作成されていることに注意してください。つまり、バイナリーはホスト Windows マシンでは実行できません。 |
CI/CD パイプラインのさまざまなステップがどのように見えるかについて、以下に概要を示しています。
-
./mvnw …
コマンドを実行するステップの出力 (つまり、ディレクトリtarget/native-image
) をビルドアーティファクトとして登録します。 -
native-image …
コマンドを実行するステップでこのアーティファクトを要求し、 -
native-image …
コマンドを実行するステップの出力 (つまり、target/*runner
に一致するファイル) をビルドアーティファクトとして登録します。
ステップ 1
を実行する環境には、Java と Maven (または Gradle) のみインストールされている必要がありますが、ステップ 3
を実行する環境には GraalVM のインストール (native-image
機能を含む) のみが必要です。
CI/CD パイプラインの最終的な出力に応じて、生成されたバイナリーがコンテナーイメージの作成に使用されます。
ネイティブ実行可能ファイルのデバッグ
ネイティブ実行可能ファイルは、 gdb
などのツールを使用してデバッグできます。
これを可能にするには、ネイティブ実行可能ファイルをデバッグシンボルとともに生成する必要があります。
デバッグシンボルの生成は Linux でのみサポートされています。 windows は開発中です。macOS はサポートされていません。 |
デバッグシンボルを生成するには、ネイティブ実行可能ファイルの生成時に -Dquarkus.native.debug.enabled=true
フラグを追加してください。ネイティブ実行可能ファイルのデバッグシンボルは、ネイティブ実行可能ファイルの隣にある .debug
ファイルにあります。
|
デバッグシンボルとは別に、 -Dquarkus.native.debug.enabled=true
フラグを設定すると、ネイティブ実行可能ファイル生成時に解決された JDK ランタイムクラス、GraalVM クラス、アプリケーションクラスのソースファイルのキャッシュが生成されます。このソースキャッシュは、シンボルと一致するソースコード間のリンクを確立するために、ネイティブデバッグツールにとって有用です。ネイティブ実行可能ファイルをデバッグする際に、必要なソースだけをデバッガー/IDEが利用できるようにする便利な方法を提供します。
Quarkusのソースコードを含むサードパーティのjar依存関係のソースは、デフォルトではソースキャッシュに追加されません。これらを含めるには、まず mvn dependency:sources
を起動してください。このステップは、これらの依存関係のソースを引き出し、ソースキャッシュに含めるために必要です。
ソースキャッシュは target/sources
フォルダーにあります。
または、
例えば、
|
ネイティブイメージのデバッグに関する詳細なガイドについては、ネイティブリファレンスガイド を参照してください。
監視オプションの使用
JDK Flight Recorder、jvmstat、ヒープダンプ、NMT (JDK 23 の Mandrel 24.1 以降)、リモート JMX などの監視オプションをネイティブ実行可能ビルドに追加できます。 ビルド時に追加するには、監視オプションのコンマ区切りリストを提供します。
-Dquarkus.native.monitoring=<comma separated list of options>
監視オプション | 説明 | 現時点での可用性 |
---|---|---|
jfr |
JDK Flight Recorder のサポートを含む |
GraalVM CE 21.3 Mandrel 21.3 |
jvmstat |
jvmstat のサポートを追加 |
GraalVM 22.3、GraalVM CE 17.0.7 Mandrel 22.3 Mandrel 23.0 (17.0.7) |
heapdump |
ヒープダンプ生成のサポートを追加 |
GraalVM 22.3、GraalVM CE 17.0.7 Mandrel 22.3 Mandrel 23.0 (17.0.7) |
jmxclient |
JMX サーバーへの接続のサポートを追加 |
GraalVM for JDK 17/20 Mandrel 23.0 |
jmxserver |
JMX クライアントからの接続を受け入れるためのサポートを追加 |
GraalVM for JDK 17/20 Mandrel 23.0 (17.0.7) |
nmt |
ネイティブメモリートラッキングのサポートを追加 |
GraalVM for JDK 23 Mandrel 24.1 |
all |
すべての監視オプションを追加 |
GraalVM 22.3、GraalVM CE 17.0.7 Mandrel 22.3 Mandrel 23.0 (17.0.7) |
これらの監視オプションの詳細は、Quarkus ネイティブリファレンスガイドを参照してください。
ネイティブ実行可能ファイルの設定
ネイティブ実行可能ファイルの生成方法に影響を与える設定オプションがたくさんあります。これらは他の設定プロパティーと同じように application.properties
で提供されています。
プロパティーは以下の通りです:
ビルド時に固定された設定プロパティー。その他の設定プロパティーは、すべて実行時にオーバーライド可能です。
Configuration property |
タイプ |
デフォルト |
||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Set to enable native-image building using GraalVM. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
Set to prevent the native-image process from actually building the native image. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
Comma-separated, additional arguments to pass to the build process. If an argument includes the Environment variable: Show more |
list of string |
|||||||||||||||||||||
If the HTTP url handler should be enabled, allowing you to do URL.openConnection() for HTTP URLs Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If the HTTPS url handler should be enabled, allowing you to do URL.openConnection() for HTTPS URLs Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
The default value for java.awt.headless JVM option. Switching this option affects linking of awt libraries. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
Defines the file encoding as in Native image runtime uses the host’s (i.e. build time) value of Environment variable: Show more |
string |
|
||||||||||||||||||||
If all character sets should be added to the native executable. Note that some extensions (e.g. the Oracle JDBC driver) also take this setting into account to enable support for all charsets at the extension level. This increases image size. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
The location of the Graal distribution Environment variable: Show more |
string |
|
||||||||||||||||||||
The location of the JDK Environment variable: Show more |
|
|||||||||||||||||||||
The maximum Java heap to be used during the native image generation Environment variable: Show more |
string |
|||||||||||||||||||||
If the native image build should wait for a debugger to be attached before running. This is an advanced option and is generally only intended for those familiar with GraalVM internals Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If the debug port should be published when building with docker and debug-build-process is true Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If isolates should be enabled Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If a JVM based 'fallback image' should be created if native image fails. This is not recommended, as this is functionally the same as just running the application in a JVM Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If all META-INF/services entries should be automatically registered Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If the bytecode of all proxies should be dumped for inspection Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If this build should be done using a container runtime. Unless container-runtime is also set, docker will be used by default. If docker is not available or is an alias to podman, podman will be used instead as the default. Environment variable: Show more |
ブーリアン |
|||||||||||||||||||||
Explicit configuration option to generate a native Position Independent Executable (PIE) for Linux. If the system supports PIE generation, the default behaviour is to disable it for performance reasons. However, some systems can only run position-independent executables, so this option enables the generation of such native executables. Environment variable: Show more |
ブーリアン |
|||||||||||||||||||||
Generate instructions for a specific machine type. Defaults to Environment variable: Show more |
string |
|||||||||||||||||||||
If this build is done using a remote docker daemon. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
The docker image to use to do the image build. It can be one of Note: Builder images are available using UBI 8 and UBI 9 base images, for example:
You need to be aware that if you use a builder image using UBI9 and you plan to build a container, you must ensure that the base image used in the container is also UBI9. Environment variable: Show more |
string |
|
||||||||||||||||||||
The strategy for pulling the builder image during the build. Defaults to 'always', which will always pull the most up-to-date image; useful to keep up with fixes when a (floating) tag is updated. Use 'missing' to only pull if there is no image locally; useful on development environments where building with out-of-date images is acceptable and bandwidth may be limited. Use 'never' to fail the build if there is no image locally. Environment variable: Show more |
|
|
||||||||||||||||||||
The container runtime (e.g. docker) that is used to do an image based build. If this is set then a container build is always done. Environment variable: Show more |
|
|||||||||||||||||||||
Options to pass to the container runtime Environment variable: Show more |
list of string |
|||||||||||||||||||||
Enable monitoring various monitoring options. The value should be comma separated.
Environment variable: Show more |
list of |
|||||||||||||||||||||
If the reports on call paths and included packages/classes/methods should be generated Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If exceptions should be reported with a full stack trace Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
If errors should be reported at runtime. This is a more relaxed setting, however it is not recommended as it means your application may fail at runtime if an unsupported feature is used by accident. Note that the use of this flag may result in build time failures due to `ClassNotFoundException`s. Reason most likely being that the Quarkus extension already optimized it away or do not actually need it. In such cases you should explicitly add the corresponding dependency providing the missing classes as a dependency to your project. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
Don’t build a native image if it already exists. This is useful if you have already built an image and you want to use Quarkus to deploy it somewhere. Note that this is not able to detect if the existing image is outdated, if you have modified source or config and want a new image you must not use this flag. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
A comma separated list of globs to match resource paths that should be added to the native image. Use slash ( By default, no resources are included. Example: Given that you have
the files Supported glob features
Note that there are three levels of escaping when passing this option via
All three levels use backslash ( Note that Quarkus extensions typically include the resources they require by themselves. This option is useful in situations when the built-in functionality is not sufficient. Environment variable: Show more |
list of string |
|||||||||||||||||||||
A comma separated list of globs to match resource paths that should not be added to the native image. Use slash ( Please refer to By default, no resources are excluded. Example: Given that you have
the resource Environment variable: Show more |
list of string |
|||||||||||||||||||||
If debug is enabled and debug symbols are generated. The symbols will be generated in a separate .debug file. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
Generate the report files for GraalVM Dashboard. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
Include a reasons entries in the generated json configuration files. Environment variable: Show more |
ブーリアン |
|
||||||||||||||||||||
The compression level in [1, 10]. 10 means best. Higher compression level requires more time to compress the executable. Environment variable: Show more |
int |
|||||||||||||||||||||
Allows passing extra arguments to the UPX command line (like --brute). The arguments are comma-separated. The exhaustive list of parameters can be found in https://github.com/upx/upx/blob/devel/doc/upx.pod. Environment variable: Show more |
list of string |
|||||||||||||||||||||
Configuration files generated by the Quarkus build, using native image agent, are informative by default. In other words, the generated configuration files are presented in the build log but are not applied. When this option is set to true, generated configuration files are applied to the native executable building process. Enabling this option should be done with care, because it can make native image configuration and/or behaviour dependant on other non-obvious factors. For example, if the native image agent generated configuration was generated from running JVM unit tests, disabling test(s) can result in a different native image configuration being generated, which in turn can misconfigure the native executable or affect its behaviour in unintended ways. Environment variable: Show more |
ブーリアン |
|
次のステップ
このガイドでは、アプリケーション用のネイティブ (バイナリー) 実行ファイルの作成について説明しました。 これにより、迅速な起動時間と少ないメモリー消費を示すアプリケーションを提供します。しかし、それだけではありません。
Kubernetes と OpenShift へのデプロイメント で探検を続けることをお勧めします。