The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

ネイティブ実行可能ファイルの生成

このガイドでは以下をカバーしています:

  • アプリケーションをネイティブ実行可能ファイルにコンパイル

  • ネイティブ実行可能ファイルのコンテナへのパッケージング

  • ネイティブ実行可能ファイルのデバッグ

このガイドは、入門ガイド で開発されたアプリケーションを入力としています。

前提条件

このガイドを完成させるには、以下が必要です:

C言語でのネイティブコンパイルのサポート

動作するC言語の開発環境があるとはどういう意味でしょうか?

  • Linuxでは、GCC、glibc、zlibヘッダが必要です。一般的なディストリビューションでは次の通りです:

    # dnf (rpm-based)
    sudo dnf install gcc glibc-devel zlib-devel libstdc++-static
    # Debian-based distributions:
    sudo apt-get install build-essential libz-dev zlib1g-dev
  • macOS では、XCode が必要な依存関係を提供します:

    xcode-select --install
  • Windowsの場合は、 Visual Studio 2017 Visual C++ Build Tools をインストールする必要があります。

背景

ネイティブな実行可能ファイルをビルドするには、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 and Mandrel のリリースを参照してください。

GraalVMの設定

This step is only required for generating native executables targeting non-Linux operating systems. For generating native executables targeting Linux, you can optionally skip this section and use a builder image instead.

If you cannot install GraalVM, you can use a multi-stage Docker build to run Maven inside a Docker container that embeds GraalVM. There is an explanation of how to do this at the end of this guide.

GraalVM for JDK 21 is required.

  1. まだの場合は、GraalVM をインストールします。これにはいくつかのオプションがあります:

  2. ランタイム環境を構成します。 GRAALVM_HOME 環境変数をGraalVMインストールディレクトリに設定します。例えば:

    export GRAALVM_HOME=$HOME/Development/mandrel/

    macOS (Mandrel ではサポート対象外) では、変数を Home のサブディレクトリに指定します:

    export GRAALVM_HOME=$HOME/Development/graalvm/Contents/Home/

    Windowsでは、コントロールパネルから環境変数を設定する必要があります。

    scoop でインストールすれば自動的に設定されます。

  3. (オプション) 環境変数 JAVA_HOME を GraalVM のインストールディレクトリに設定します。

    export JAVA_HOME=${GRAALVM_HOME}
  4. (オプション) GraalVM bin ディレクトリをパスに追加します

    export PATH=${GRAALVM_HOME}/bin:$PATH
Issues using GraalVM with macOS

GraalVM binaries are not (yet) notarized for macOS as reported in this GraalVM issue. This means that you may see the following error when using native-image:

“native-image” cannot be opened because the developer cannot be verified

回避策として、次のコマンドを使用して、GraalVMインストールディレクトリ上の com.apple.quarantine 拡張属性を再帰的に削除します:

xattr -r -d com.apple.quarantine ${GRAALVM_HOME}/../..

ソリューション

次のセクションの手順に従って、アプリケーションを段階的にパッケージ化することをお勧めします。しかしながら、完成したサンプルに直接進むこともできます。

Git リポジトリのクローンを作成: git clonehttps://github.com/quarkusio/quarkus-quickstarts.git、または アーカイブ をダウンロードします。

ソリューションは getting-started ディレクトリに存在します。

ネイティブ実行可能ファイルの生成

アプリケーションのネイティブ実行可能ファイルには、アプリケーション・コード、必要なライブラリ、Java API、および VM の縮小版が含まれます。VM ベースが小さくなることで、アプリケーションの起動時間が改善され、ディスクフットプリントが最小限に抑えられます。

ネイティブ実行可能ファイルの生成

If you have generated the application from the previous tutorial, you can find in the pom.xml the following Maven profile section:

<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>

<quarkus.native.additional-build-args> プロパティーを使用して、 native-image コマンドにカスタムオプションを指定できます。複数のオプションはカンマで区切ることができます。

もう一つの可能性は、 application.propertiesquarkus.native.additional-build-args 設定プロパティーを含めることです。

ネイティブイメージビルド処理の設定方法については、以下の [設定リファレンス] の項で詳しく説明しています。

We use a profile because, you will see very soon, packaging the native executable takes a few minutes. You could just pass -Dquarkus.native.enabled=true as a property on the command line, however it is better to use a profile as this allows native image tests to also be run.

次のようにネイティブ実行可能ファイルの作成します:

コマンドラインインタフェース
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true
Windows でのパッケージ化に関する問題

The Microsoft Native Tools for Visual Studio must first be initialized before packaging. You can do this by starting the x64 Native Tools Command Prompt that was installed with the Visual Studio Build Tools. At the x64 Native Tools Command Prompt, you can navigate to your project folder and run ./mvnw package -Dnative.

もう一つのソリューションは、これを行うためのスクリプトを書くことです:

cmd /c 'call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && mvn package -Dnative'

通常のファイルに加えて、このビルドでは target/getting-started-1.0-SNAPSHOT-runner を生成します。これを実行するには、次のようにします: ./target/getting-started-1.0-SNAPSHOT-runner .

Java プレビュー機能

プレビュー機能に依存する Java コードには、特別な注意が必要です。これは、ネイティブ実行可能ファイルを生成する場合、--enable-preview フラグを基になるネイティブイメージ呼び出しに渡す必要があることを意味します。そのためには、フラグの前に -J を付け、それを追加のネイティブビルド引数として渡します: -Dquarkus.native.additional-build-args=-J—​enable-preview

完全に静的なネイティブ実行可能ファイルの作成

完全に静的なネイティブ実行可能ファイルのサポートは実験的なものです。

On Linux it’s possible to package a native executable that doesn’t depend on any system shared library. There are some system requirements to be fulfilled and additional build arguments to be used along with the native-image invocation, a minimum is -Dquarkus.native.additional-build-args="--static","--libc=musl".

完全な静的バイナリのコンパイルは、 glibc の代わりに musl を静的にリンクすることで行われます。厳密なテストなしに実運用で使用するべきではありません。

ネイティブ実行可能ファイルのテスト

ネイティブ実行可能ファイルを生成することはいくつかの問題を引き起こす可能性があるので、ネイティブファイルで実行されているアプリケーションに対していくつかのテストを実行することをお勧めします。その理由は テストのガイド で説明されています。

To see the GreetingResourceIT run against the native executable, use ./mvnw verify -Dnative:

$ ./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/ubi-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
...

By default, Quarkus waits for 60 seconds for the native image to start before automatically failing the native tests. This duration can be changed using the quarkus.test.wait-time system property. For example, to increase the duration to 300 seconds, use: ./mvnw verify -Dnative -Dquarkus.test.wait-time=300.

この手順は、以前は @NativeImageTest のアノテーションを使用していました。 @NativeImageTest@QuarkusIntegrationTest に置き換えられ、 @NativeImageTest のテスト機能のスーパーセットを提供します。 @QuarkusIntegrationTest の詳細については、 テストガイド を参照してください。

プロファイル

デフォルトでは、インテグレーションテストは prod プロファイルを使用して、ネイティブの実行可能ファイルに対して buildrun の両方を行います。

You can override the profile the executable runs with during the test using the quarkus.test.native-image-profile property. Either by adding it to application.properties or by appending it to the command line: ./mvnw verify -Dnative -Dquarkus.test.native-image-profile=test. Your %test. prefixed properties will be used at the test runtime.

You can override the profile the executable is built with and runs with using the quarkus.profile=test property, e.g. ./mvnw clean verify -Dnative -Dquarkus.profile=test. This might come handy if there are test specific resources to be processed, such as importing test data into the database.

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 リソースのみが含まれ、余分なテストデータは含まれません。

The executable built with -Dquarkus.profile=test is not suitable for production deployment. It contains your test resources files and settings. Once the testing is done, the executable would have to be built again, using the default, prod profile.

Alternatively, if you need to specify specific properties when running tests against the native executable built using the prod profile, an option is to put those properties in file src/test/resources/application-nativeit.yaml, and refer to it from the failsafe plugin configuration using the QUARKUS_CONFIG_LOCATIONS environment variable. For instance:

<plugin>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>${surefire-plugin.version}</version>
  <executions>
    <execution>
      <goals>
        <goal>integration-test</goal>
        <goal>verify</goal>
      </goals>
      <configuration>
        <systemPropertyVariables>
          <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
          <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
          <maven.home>${maven.home}</maven.home>
        </systemPropertyVariables>
        <environmentVariables>
          <QUARKUS_CONFIG_LOCATIONS>./src/test/resources/application-nativeit.yaml</QUARKUS_CONFIG_LOCATIONS>
        </environmentVariables>
      </configuration>
    </execution>
  </executions>
</plugin>

Java プレビュー機能

Java プレビュー機能

プレビュー機能に依存する Java コードには、特別な注意が必要です。つまり、ネイティブ実行可能ファイルをテストする場合は、--enable-preview フラグを Surefire プラグインに渡す必要があります。その方法の 1 つが、<argLine>--enable-preview</argLine>configuration セクションに追加する方法です。

ネイティブ実行可能ファイルとして実行している場合のテストの除外

この方法でテストを実行する場合、実際にネイティブで実行されるのはアプリケーションのエンドポイントのみで、HTTP 呼び出しでしかテストできません。テストコードは実際にはネイティブには実行されないので、HTTP エンドポイントを呼び出さないコードをテストしている場合は、それらをネイティブテストの一部として実行するのは良い考えではないでしょう。

上記のようにJVMとネイティブ実行でテストクラスを共有している場合、特定のテストをネイティブイメージに対してテストをするときに、@DisabledOnNativeImage アノテーションを付けてそれらをスキップできます。

@DisabledOnIntegrationTest を使用すると、JVM モード、コンテナイメージ、ネイティブイメージでのアプリケーションのテストを含む、すべての統合テストインスタンスでのテストも無効になります。

既存のネイティブ実行可能ファイルのテスト

It is also possible to re-run the tests against a native executable that has already been built. To do this run ./mvnw test-compile failsafe:integration-test -Dnative. This will discover the existing native image and run the tests against it using failsafe.

何らかの理由でプロセスがネイティブイメージを見つけられない場合や、ターゲットディレクトリーにないネイティブイメージをテストしたい場合は、 -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.
Maven
./mvnw install -Dnative -DskipTests -Dquarkus.native.container-build=true
Gradle
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true

デフォルトでは、Quarkusはコンテナランタイムを自動的に検出します。コンテナランタイムを明示的に選択したい場合は、次のようにします:

Docker の場合:

コマンドラインインタフェース
quarkus build --native -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=docker
Maven
./mvnw install -Dnative -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=docker
Gradle
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=docker

podman の場合:

コマンドラインインタフェース
quarkus build --native -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podman
Maven
./mvnw install -Dnative -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podman
Gradle
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podman

These are regular Quarkus config properties, so if you always want to build in a container it is recommended you add these to your application.properties in order to avoid specifying them every time.

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

この場合、パラメータ -Dquarkus.native.container-build=true の代わりに -Dquarkus.native.remote-container-build=true を使用してください。

その理由は、 -Dquarkus.native.container-build=true を通して起動されるローカルビルドドライバは、ビルドコンテナで JAR を利用できるようにするためにボリュームマウントを使用しますが、ボリュームマウントはリモートデーモンでは機能しません。リモートコンテナのビルドドライバは、必要なファイルをマウントするのではなく、コピーします。リモートドライバはローカルデーモンでも動作しますが、ローカルの場合はローカルドライバを使用した方が良いことに注意してください。なぜなら、マウントの方がコピーよりもパフォーマンスが高いからです。

Building with GraalVM instead of Mandrel requires a custom builder image parameter to be passed additionally:

コマンドラインインタフェース
quarkus build --native -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=graalvm
Maven
./mvnw install -Dnative -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=graalvm
Gradle
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true -Dquarkus.native.builder-image=graalvm

上記のコマンドはイメージが更新されるフローティングタグを指していることに注意してください。ビルダーイメージを最新かつ安全に保つために、フローティングタグを使用することを強く推奨します。どうしても必要な場合は、特定のタグをハードコーディングしても構いませんが(利用可能なタグについては こちらを参照してください)、その方法ではセキュリティーアップデートが受けられず、サポートされていないことに注意してください。

コンテナの作成

コンテナイメージのエクステンションの使用

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デーモンを実行している場合、 -Dquarkus.native.container-build=true-Dquarkus.native.remote-container-build=true で置換する必要があります。

  • quarkus.container-image.build=true 最終的なアプリケーションアーティファクト(この場合はネイティブ実行可能ファイル)を使用してコンテナイメージを作成するようにQuarkusに指示します。

詳細については、 コンテナイメージガイド を参照してください。

マイクロベースイメージを手動で使用する方法

Quarkus Mavenプラグインで生成されたJARを使用して、コンテナー内でアプリケーションを実行することができます。ただし、このセクションでは、生成されたネイティブ実行可能ファイルを使用してコンテナーイメージを作成することに焦点を当てます。

Containerization Process

ローカルのGraalVMインストール環境を使用する場合、ネイティブ実行可能ファイルは、ローカルのオペレーティングシステム(Linux、macOS、Windowsなど)をターゲットにしています。しかし、コンテナーはオペレーティングシステムによって生成されたものと同じ 実行 形式を使用しない場合があるため、コンテナーランタイムを活用して実行形式を生成するようにMavenビルドに指示します(この セクション で説明されているように)。

生成される実行ファイルは 64 ビットの Linux 実行ファイルになるので、お使いの OS によっては実行できなくなる可能性があります。しかし、コンテナにコピーするので問題ありません。プロジェクト生成では、 src/main/docker ディレクトリに Dockerfile.native-micro を用意し、以下のような内容にしています:

FROM quay.io/quarkus/quarkus-micro-image:2.0
WORKDIR /work/
COPY target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
Quarkus マイクロイメージとは?

Quarkus マイクロイメージは、ネイティブアプリケーションを実行するための適切な依存関係のセットを提供する小さなコンテナイメージです。これは UBI Micro に基づいています。このベースイメージは、コンテナで完全に機能するように調整されています。

UBI イメージの詳細については、以下をご覧ください:

UBI イメージは制限なく使用できます。

このページ では、アプリケーションに特定の要件がある場合に、quarkus-micro イメージを拡張する方法について説明しています。

あとは、生成されたネイティブ実行可能ファイルを削除していなければ、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/ubi8/ubi-minimal:8.9
WORKDIR /work/
RUN chown 1001 /work \
    && chmod "g+rwX" /work \
    && chown 1001:root /work
COPY --chown=1001:root target/*-runner /work/application

EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

UBI の最小イメージは、上記のマイクロイメージよりも大きくなっています。これには、microdnf パッケージマネージャーなどのユーティリティーが含まれています。

マルチステージDockerビルドの使用

前のセクションでは、Maven または Gradle を使用してネイティブ実行可能ファイルをビルドする方法を示しましたが、その場合は最初にネイティブ実行可能ファイルを作成しておく必要があります。さらに、このネイティブ実行可能ファイルは Linux64 ビットの実行可能ファイルである必要があります。

ビルドツールを含む最終的なコンテナを用意せずに、ネイティブ実行可能ファイルをコンテナに直接ビルドする必要がある場合もあるはずです。このアプローチは、マルチステージの Docker ビルドで使用可能です:

  1. 最初の段階では、Maven または Gradle を使用してネイティブ実行可能ファイルをビルドします

  2. 第 2 段階は、生成されたネイティブ実行可能ファイルをコピーする最小限のイメージです

以下のDockerファイルからコンテナイメージをビルドする前に、デフォルトの .dockerignore ファイルを更新する必要があります。これは、target ディレクトリ以のすべてがフィルタリングされるためです。コンテナ内でビルドするため、src ディレクトリをコピーする必要があります。そのために、.dockerignore を編集し、その内容を更新し、* の行を削除します。

このような多段階を用いたビルドは、次のように実現できます:

MavenでビルドするためのサンプルDockerfileです:

## Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/ubi-quarkus-mandrel-builder-image:jdk-21 AS build
COPY --chown=quarkus:quarkus 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.1.2:go-offline
COPY src /code/src
RUN ./mvnw package -Dnative

## Stage 2 : create the docker final image
FROM quay.io/quarkus/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 -N org.apache.maven.plugins:maven-wrapper-plugin:3.1.1: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/ubi-quarkus-mandrel-builder-image:jdk-21 AS build
USER root
RUN microdnf install findutils
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/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利用ガイド を参照してください。

To use GraalVM CE instead of Mandrel, update the FROM clause to: FROM quay.io/quarkus/ubi-quarkus-graalvmce-builder-image:jdk-21 AS build.

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/ubi-quarkus-graalvmce-builder-image:jdk-21 AS build
USER root
RUN microdnf install make gcc
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.1.2: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 とネイティブイメージのコンパイルの分離

In certain circumstances, you may want to build the native image in a separate step. For example, in a CI/CD pipeline, you may want to have one step to generate the source that will be used for the native image generation and another step to use these sources to actually build the native executable. For this use case, you can set the additional flag quarkus.native.sources-only=true. This will execute the java compilation as if you had started native compilation (-Dnative), but stops before triggering the actual call to GraalVM’s 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

From the output above one can see that, in addition to the produced jar file and the associated lib directory, a text file named native-image.args was created. This file holds all parameters (including the name of the JAR to compile) to pass along to GraalVM’s native-image command. A text file named graalvm.version was also created and holds the GraalVM version that should be used. If you have GraalVM installed and it matches this version, you can start the native compilation by executing:

$ 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 パイプラインのさまざまなステップがどのように見えるかについて、以下に概要を示しています。

  1. ./mvnw …​ コマンドを実行するステップの出力 (つまり、ディレクトリ target/native-image) をビルドアーティファクトとして登録します。

  2. native-image …​ コマンドを実行するステップでこのアーティファクトを要求し、

  3. native-image …​ コマンドを実行するステップの出力 (つまり、target/*runner に一致するファイル) をビルドアーティファクトとして登録します。

ステップ 1 を実行する環境には、Java と Maven (または Gradle) のみインストールされている必要がありますが、ステップ 3 を実行する環境には GraalVM のインストール (native-image 機能を含む) のみが必要です。

CI/CD パイプラインの最終的な出力に応じて、生成されたバイナリーがコンテナイメージの作成に使用されます。

ネイティブ実行可能ファイルのデバッグ

Native executables can be debugged using tools such as gdb. For this to be possible native executables need to be generated with debug symbols.

デバッグシンボル生成はLinuxでのみサポートされています。 windowsは開発中です。macOSはサポートされていません。

デバッグシンボルを生成するには、ネイティブ実行可能ファイルの生成時に -Dquarkus.native.debug.enabled=true フラグを追加してください。ネイティブ実行可能ファイルのデバッグシンボルは、ネイティブ実行可能ファイルの隣にある .debug ファイルにあります。

The generation of the .debug file depends on objcopy. As a result, when using a local GraalVM installation on common Linux distributions you will need to install the binutils package:

# dnf (rpm-based)
sudo dnf install binutils
# Debian-based distributions
sudo apt-get install binutils

objcopy が利用できない場合、デバッグシンボルが実行可能ファイルに埋め込まれています。

デバッグシンボルとは別に、 -Dquarkus.native.debug.enabled=true フラグを設定すると、ネイティブ実行可能ファイル生成時に解決された JDK ランタイムクラス、GraalVM クラス、アプリケーションクラスのソースファイルのキャッシュが生成されます。このソースキャッシュは、シンボルと一致するソースコード間のリンクを確立するために、ネイティブデバッグツールにとって有用です。ネイティブ実行可能ファイルをデバッグする際に、必要なソースだけをデバッガー/IDEが利用できるようにする便利な方法を提供します。

Quarkusのソースコードを含むサードパーティのjar依存関係のソースは、デフォルトではソースキャッシュに追加されません。これらを含めるには、まず mvn dependency:sources を起動してください。このステップは、これらの依存関係のソースを引き出し、ソースキャッシュに含めるために必要です。

ソースキャッシュは target/sources フォルダーにあります。

gdbtarget とは異なるディレクトリから実行している場合、ソースは以下を

directory path/to/target

gdb プロンプトで実行することで読み込まれます。

または、 gdb を以下のように起動してください:

gdb -ex 'directory path/to/target' path/to/target/{project.name}-{project.version}-runner

例えば、

gdb -ex 'directory ./target' ./target/getting-started-1.0.0-SNAPSHOT-runner

ネイティブイメージのデバッグに関する詳細なガイドについては、ネイティブリファレンスガイド を参照してください。

Using Monitoring Options

Monitoring options such as JDK flight recorder, jvmstat, heap dumps, and remote JMX (experimental in Mandrel 23) can be added to the native executable build. Simply supply a comma separated list of the monitoring options you wish to include at build time.

-Dquarkus.native.monitoring=<comma separated list of options>
Monitoring Option 説明 Availability As Of

jfr

Include JDK Flight Recorder support

GraalVM CE 21.3 Mandrel 21.3

jvmstat

Adds jvmstat support

GraalVM 22.3, GraalVM CE 17.0.7 Mandrel 22.3 Mandrel 23.0 (17.0.7)

heapdump

Adds support for generating heap dumps

GraalVM 22.3, GraalVM CE 17.0.7 Mandrel 22.3 Mandrel 23.0 (17.0.7)

jmxclient

Adds support for connections to JMX servers.

GraalVM for JDK 17/20 Mandrel 23.0

jmxserver

Adds support for accepting connections from JMX clients.

GraalVM for JDK 17/20 Mandrel 23.0 (17.0.7)

all

Adds all monitoring options.

GraalVM 22.3, GraalVM CE 17.0.7 Mandrel 22.3 Mandrel 23.0 (17.0.7)

Please see the Quarkus Native Reference Guide for more detailed information on these monitoring options.

ネイティブ実行可能ファイルの設定

ネイティブ実行可能ファイルの生成方法に影響を与える設定オプションがたくさんあります。これらは他の設定プロパティーと同じように application.properties で提供されています。

プロパティーは以下の通りです:

ビルド時に固定される設定プロパティ - その他の設定プロパティは実行時にオーバーライド可能です。

Configuration property

デフォルト

Set to enable native-image building using GraalVM.

Environment variable: QUARKUS_NATIVE_ENABLED

Show more

boolean

false

Set to prevent the native-image process from actually building the native image.

Environment variable: QUARKUS_NATIVE_SOURCES_ONLY

Show more

boolean

false

Comma-separated, additional arguments to pass to the build process. If an argument includes the , symbol, it needs to be escaped, e.g. \\,

Environment variable: QUARKUS_NATIVE_ADDITIONAL_BUILD_ARGS

Show more

list of string

If the HTTP url handler should be enabled, allowing you to do URL.openConnection() for HTTP URLs

Environment variable: QUARKUS_NATIVE_ENABLE_HTTP_URL_HANDLER

Show more

boolean

true

If the HTTPS url handler should be enabled, allowing you to do URL.openConnection() for HTTPS URLs

Environment variable: QUARKUS_NATIVE_ENABLE_HTTPS_URL_HANDLER

Show more

boolean

false

The default value for java.awt.headless JVM option. Switching this option affects linking of awt libraries.

Environment variable: QUARKUS_NATIVE_HEADLESS

Show more

boolean

true

Defines the file encoding as in -Dfile.encoding=…​. Native image runtime uses the host’s (i.e. build time) value of file.encoding system property. We intentionally default this to UTF-8 to avoid platform specific defaults to be picked up which can then result in inconsistent behavior in the generated native executable.

Environment variable: QUARKUS_NATIVE_FILE_ENCODING

Show more

String

UTF-8

If all character sets should be added to the native image. This increases image size

Environment variable: QUARKUS_NATIVE_ADD_ALL_CHARSETS

Show more

boolean

false

The location of the Graal distribution

Environment variable: QUARKUS_NATIVE_GRAALVM_HOME

Show more

string

${GRAALVM_HOME:}

The location of the JDK

Environment variable: QUARKUS_NATIVE_JAVA_HOME

Show more

File

${java.home}

The maximum Java heap to be used during the native image generation

Environment variable: QUARKUS_NATIVE_NATIVE_IMAGE_XMX

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: QUARKUS_NATIVE_DEBUG_BUILD_PROCESS

Show more

boolean

false

If the debug port should be published when building with docker and debug-build-process is true

Environment variable: QUARKUS_NATIVE_PUBLISH_DEBUG_BUILD_PROCESS_PORT

Show more

boolean

true

If isolates should be enabled

Environment variable: QUARKUS_NATIVE_ENABLE_ISOLATES

Show more

boolean

true

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: QUARKUS_NATIVE_ENABLE_FALLBACK_IMAGES

Show more

boolean

false

If all META-INF/services entries should be automatically registered

Environment variable: QUARKUS_NATIVE_AUTO_SERVICE_LOADER_REGISTRATION

Show more

boolean

false

If the bytecode of all proxies should be dumped for inspection

Environment variable: QUARKUS_NATIVE_DUMP_PROXIES

Show more

boolean

false

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: QUARKUS_NATIVE_CONTAINER_BUILD

Show more

boolean

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: QUARKUS_NATIVE_PIE

Show more

boolean

If this build is done using a remote docker daemon.

Environment variable: QUARKUS_NATIVE_REMOTE_CONTAINER_BUILD

Show more

boolean

false

The docker image to use to do the image build. It can be one of graalvm, mandrel, or the full image path, e.g. quay.io/quarkus/ubi-quarkus-mandrel-builder-image:jdk-21.

Environment variable: QUARKUS_NATIVE_BUILDER_IMAGE

Show more

string

mandrel

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: QUARKUS_NATIVE_BUILDER_IMAGE_PULL

Show more

always, missing, never

always

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: QUARKUS_NATIVE_CONTAINER_RUNTIME

Show more

docker, docker-rootless, wsl, wsl-rootless, podman, podman-rootless, unavailable

Options to pass to the container runtime

Environment variable: QUARKUS_NATIVE_CONTAINER_RUNTIME_OPTIONS

Show more

list of string

Enable monitoring various monitoring options. The value should be comma separated.

  • jfr for JDK flight recorder support

  • jvmstat for JVMStat support

  • heapdump for heampdump support

  • jmxclient for JMX client support (experimental)

  • jmxserver for JMX server support (experimental)

  • all for all monitoring features

Environment variable: QUARKUS_NATIVE_MONITORING

Show more

list of MonitoringOption

If the reports on call paths and included packages/classes/methods should be generated

Environment variable: QUARKUS_NATIVE_ENABLE_REPORTS

Show more

boolean

false

If exceptions should be reported with a full stack trace

Environment variable: QUARKUS_NATIVE_REPORT_EXCEPTION_STACK_TRACES

Show more

boolean

true

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.

Environment variable: QUARKUS_NATIVE_REPORT_ERRORS_AT_RUNTIME

Show more

boolean

false

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: QUARKUS_NATIVE_REUSE_EXISTING

Show more

boolean

false

A comma separated list of globs to match resource paths that should be added to the native image.

Use slash (/) as a path separator on all platforms. Globs must not start with slash.

By default, no resources are included.

Example: Given that you have src/main/resources/ignored.png and src/main/resources/foo/selected.png in your source tree and one of your dependency JARs contains bar/some.txt file, with the following configuration

quarkus.native.resources.includes = foo/**,bar/**/*.txt

the files src/main/resources/foo/selected.png and bar/some.txt will be included in the native image, while src/main/resources/ignored.png will not be included.

Supported glob features Feature Description * Matches a (possibly empty) sequence of characters that does not contain slash (/) ** Matches a (possibly empty) sequence of characters that may contain slash (/) ? Matches one character, but not slash [abc] Matches one character given in the bracket, but not slash [a-z] Matches one character from the range given in the bracket, but not slash [!abc] Matches one character not named in the bracket; does not match slash [a-z] Matches one character outside the range given in the bracket; does not match slash {one,two,three} Matches any of the alternating tokens separated by comma; the tokens may contain wildcards, nested alternations and ranges \ The escape character

Note that there are three levels of escaping when passing this option via application.properties:

  1. application.properties parser

    • MicroProfile Config list converter that splits the comma separated list

    • Glob parser All three levels use backslash (\) as the escaping character. So you need to use an appropriate number of backslashes depending on which level you want to escape.

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: QUARKUS_NATIVE_RESOURCES_INCLUDES

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 (/) as a path separator on all platforms. Globs must not start with slash.

Please refer to includes for details about the glob syntax.

By default, no resources are excluded.

Example: Given that you have src/main/resources/red.png and src/main/resources/foo/green.png in your source tree and one of your dependency JARs contains bar/blue.png file, with the following configuration

quarkus.native.resources.includes = **/*.png
quarkus.native.resources.excludes = foo/**,**/green.png

the resource red.png will be available in the native image while the resources foo/green.png and bar/blue.png will not be available in the native image.

Environment variable: QUARKUS_NATIVE_RESOURCES_EXCLUDES

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: QUARKUS_NATIVE_DEBUG_ENABLED

Show more

boolean

false

Generate the report files for GraalVM Dashboard.

Environment variable: QUARKUS_NATIVE_ENABLE_DASHBOARD_DUMP

Show more

boolean

false

The compression level in [1, 10]. 10 means best.

Higher compression level requires more time to compress the executable.

Environment variable: QUARKUS_NATIVE_COMPRESSION_LEVEL

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: QUARKUS_NATIVE_COMPRESSION_ADDITIONAL_ARGS

Show more

list of string

次のステップ

このガイドでは、アプリケーション用のネイティブ(バイナリー)実行ファイルの作成について説明しました。これにより、迅速な起動時間と少ないメモリー消費を示すアプリケーションを提供します。しかし、それだけではありません。

Kubernetes と OpenShift へのデプロイメント で探検を続けることをお勧めします。

関連コンテンツ