QuarkusとPodman DesktopでJavaコンテナを管理する

Red Hatでソリューションアーキテクトをしている田中司恩(@tnk4on)です。

この記事は Red Hat DeveloperManaging Java containers with Quarkus and Podman Desktop を、許可をうけて翻訳したものです。

本記事で紹介する Podman や Podman Desktop に関する情報を日本語で紹介するTwitter アカウントがあります。こちらもフォローして情報収集に活用ください。(ハッシュタグ #podmanjp)


https://developers.redhat.com/sites/default/files/styles/article_feature/public/ST-containers_2x.png?itok=MxQgWIGQ

ソフトウェア開発の世界は急速に変化しており、Java開発者も例外ではありません。Javaコンテナを管理するために新しいスキルを学ぶ必要があります。

従来のJava開発の世界では、Javaアーティファクト(それが.jarであれ、.warであれ、.earであれ)を構築し、「壁の向こうに放り投げて」ミドルウェアや運用担当者に引き渡すのが一般的でした。というのも、エンタープライズ・アプリケーション・サーバーの設定と実行は必ずしも簡単ではなく、最終的には、開発者のラップトップはステージング環境や本番環境の仕様とおそらく一致しないため、いずれにせよ設定が異なってしまうからです。結局のところ、私たちは皆、「私のマシンでは動く」という決まり文句を知っています。

最近では、物事はより速く、より優れたデリバリー(delivery)を必要とし、本番環境での問題は、しばしば非常に迅速な方法で解決する必要があります。というのも、ダウンタイムの1秒1秒が、組織の収益損失を引き起こす可能性があるからです。アプリケーションを提供する新しい方法が考え出され、それに伴い、クラウドネイティブ・アプリケーション、コンテナDevOpsが登場しました。「でも、私のマシンでは動いた」という言い訳はもはや通用しません。

Java開発者はコンテナで作業できる必要があります。コンテナは、ローカル・マシンの本番環境に近い環境でアプリケーションをテストする実用的な方法だからです。開発者や組織の中には、ローカルマシンからクラウドへと開発を移行し、IDE 自身を再現可能なコンテナ化された環境で実行することで、一貫性をさらに高めることを選択する人もいます。Red Hat OpenShift Dev Spacesはこれを実現する1つの方法ですが、この記事の範囲外です。

Javaを使用したコンテナの構築

しかし、コンテナの構築と管理は、Java開発者にとってはすぐに圧倒されてしまいます。表面的には、アーティファクトをベース・イメージにコピーする指示とともに Dockerfileを作成し、Dockerビルドを行う「だけ」の問題です。しかし実際には、アプリケーションからコンテナイメージを作成するには、それ以上に多くのことを考慮する必要があります。

ベースイメージの選択

まず始めに、ベースイメージが必要です。ゼロから始めて依存関係を個別に追加するのか?それともすでにJava仮想マシン(JVM)実装が含まれているベースイメージを使うのか?あるいは、アプリケーションのネイティブビルドを選択し、コンテナ内でJVMを実行する必要がないかもしれません。いずれにせよ、テスト済みでセキュリティが確保され、理想的には署名され、Open Container Initiative (OCI)に準拠し、対象としている特定のJavaバージョンの安定したイメージを提供している信頼できるソースを見つける必要があります。そして願わくば、このソースがサポートを提供し、将来にわたってパッチを保守し、バックポートしてくれることを期待します。ベースイメージは、おそらくパフォーマンスを最適化するためのチューニングも必要になるでしょう。

Red HatのUniversal Base Images (UBI)は、コンテナイメージを構築するための良い出発点です。UBIは無償で使用でき、Red Hat Enterprise Linux(RHEL)ディストリビューションのサブセットを中核としており、コンテナ構築のための安定した、安全な、最適化された、信頼性の高い基盤を提供すします。いくつかのJVMベースのUBIイメージが利用可能で、ネイティブバイナリをデプロイするためのUBI-microもあります。

コンテナ・イメージの構築

ベースイメージが決まったら、コンテナイメージをビルドする方法が必要になります。最もよく知られている方法は、Dockerfile(またはContainerfile)を作成し、それをDockerでビルドすることです。

しかし、これはコンテナをビルドする唯一の方法ではありません。同じContainerfileを使ってPodmanでイメージをビルドすることもできます。Podmanは完全にオープンソースのコンテナエンジンで、Dockerエンジンよりもかなり多くの機能を備えています。また、Buildahという、コンテナイメージを構築するために特別に作られた別のオープンソースツールを使うこともできます。

Containerfileを必要とせずにコンテナをビルドする方法もあります。Source2Image (S2I)BuildpacksJibなどのビルドツールがあります。これらのツールの複雑さはさまざまですが、いずれもコンテナのビルドプロセスを合理化することを目的としており、特に開発者にとっては便利です。

例えば、JibはJavaでコンテナイメージをビルドするために特別に作られたビルドツールです。S2Iは、ソースコードを受け取って、それがどのようなアプリケーションなのかを調べるためにイントロスペクションを行い(例えば、pom.xmlがあればJavaアプリケーションであることを示す)、S2Iツールによって事前に定義されたビルドイメージや、ユーザーによって提供されたカスタムビルドイメージを使用して、アプリケーションのソースコードからコンテナイメージをビルドするツールです。Buildpacksも同様に動作しますが、Buildpacksビルダーイメージが必要です。

デメリットとしては、これらのコンテナビルドツールごとに特定のコマンドラインインターフェース(CLI)プログラムをインストールし、それらの使い方を理解する必要があるということです。さらに、これらのビルドツールが使用するベースイメージ (該当する場合) を知るか、自分で用意し、それらが安全に使用できるかどうかを判断する必要があります。

コンテナ用語の詳細については、Scott McCartyがこの記事で包括的な紹介をしています。

QuarkusがContainerfileをどのようにサポートするのか

QuarkusはJavaスタックで、Java開発者がクラウドネイティブな開発を容易にできるようにすることを目的としています。Quarkusは、Quarkus CLIquarkus create app コマンドの実行や、code.quarkus.io 上でのスタータープロジェクトの生成、VS CodeやIntelliJでのQuarkusプラグインの使用など、開発者がQuarkusアプリケーションをブートストラップした瞬間からContainerfileを提供します。

新しいQuarkusアプリケーションをブートストラップすることで、src/main/dockerに、この記事で以前に紹介したUBIイメージに基づく事前に準備されたContainerfile(この場合、Dockerfile.*という名前)が入ったフォルダが作成されます(図1)。

https://developers.redhat.com/sites/default/files/styles/article_floated/public/screenshot_from_2023-04-28_18-36-35.png?itok=roN3aXaF

図1:アプリケーションのブートストラップ時にQuarkusが提供するDockerfile

Quarkusには、使用ケースに応じて4種類のコンテナファイルが用意されています:

  • Dockerfile.jvm はデフォルトで使用され、QuarkusアプリケーションをJVMモードで実行するJavaコンテナを構築します。
  • Dockerfile.legacy-jar`はlegacy-jarパッケージングタイプ(Quarkusのlegacy対fast-jarの詳細)の場合に使用されます。
  • Dockerfile.native はネイティブにコンパイルされたQuarkusアプリを実行するためにJVMなしのUBIを使用します。
  • Dockerfile.native-microはネイティブのQuarkusアプリを実行するためのカスタムビルドのUBI-microイメージです。

これらのコンテナファイルは通常のDockerやPodmanコマンドで使用できますが、QuarkusではMavenやGradleなどのビルドツールから直接コンテナイメージをビルドすることもできます。基本的には、例えばmvn package quarkus:image-buildでイメージをビルドすることができ、QuarkusはデフォルトでQuarkusプロジェクトに付属しているDockerfile.jvmを使用してコンテナイメージを自動的にビルドします。

同様に、ネイティブにコンパイルされたバイナリを実行するJVMなしでイメージをビルドするには、コマンド(この場合はMaven)に--Dnativeパラメータを追加するだけです。

後者のコマンドには1つ注意点があります。GraalVM Native Image Builderの実行ファイル(native-imageと呼ばれる)をインストールする必要があります。しかし、Quarkusには、native-image実行ファイルをローカルにインストールすることなく、GraalVMのNative Image Buildを活用する代替方法があります。Quarkusは実際、ネイティブイメージ実行ファイルがないことを検出し、ネイティブJavaコンパイルを行うビットを含むコンテナイメージのダウンロードを試み、コンテナ内でネイティブバイナリを実際にビルドします(もちろん、DockerまたはPodmanがインストールされていることが前提です)。ネイティブ・バイナリー・ビルダー・イメージはMandrelに基づいています。これはGraalVMコミュニティ・エディションのダウンストリーム・ディストリビューションで、特にQuarkusをサポートするためのネイティブ・イメージ・リリースを提供することを主な目的としています。

Quarkusを使ったCLIのさらなるマジック

Quarkus CLIは、要するに、MavenやGradleビルドツールの便利なラッパーであり、プロジェクトの作成、Quarkusの開発モードやテストモードでの起動、拡張機能の管理、ビルド、開発、デプロイを行うことができます。ツールを切り替えることなく、完全なインナーループ開発体験をコントロールする方法を提供します。

Quarkus CLIのおかげで、quarkus image buildのような覚えやすいシンプルなコマンドを実行できます。舞台裏では、Quarkusが選択したビルドツールを起動し、アプリケーションをパッケージ化し、前述のContainerfileとローカルのDockerまたはPodmanインスタンスを使用してコンテナイメージをビルドします(図2を参照)。

同様に、JibまたはBuildpacksを使用するには、同じコマンドを実行し、quarkus image build jibまたはquarkus image build buildpackのように、好みのコンテナビルドツールを追加で指定します。

https://developers.redhat.com/sites/default/files/styles/article_floated/public/screenshot_from_2023-05-15_13-54-00.png?itok=2Ml9XAXI

図2:Quarkusイメージビルドの実行後のイメージビルドの成功メッセージ

Quarkus CLI では、quarkus image push を使用して、コンテナイメージをレジストリにプッシュすることもできます。例えば、quarkus image push --also-buildのように--also-buildフラグを追加することで、アプリケーションのビルド、コンテナのビルド、コンテナのプッシュを一度に行うことができます。あるいは、ネイティブにコンパイルされたバイナリとして、quarkus image push --also-build --nativeとすることもできる。

Podman Desktopでコンテナを管理・実行する

コンテナイメージがビルドされたら、そのコンテナが実際に動作することを確認したり、他のアプリケーショ ンで使用したりするために、コンテナを実行したくなるでしょう。podman rundocker runといったPodmanやDockerコマンドの使い方を学ぶこともできますが、ポートの公開、ボリュームのマウント、コマンドの実行など、少なくともこれらのツールに関する専門知識が必要になります。

Podman Desktopは直感的なユーザーエクスペリエンスでコンテナの実行と管理をより簡単にするUIツールです。Windows(WSL付き)、macOS、Linuxにインストールでき、必要に応じて基礎となるPodmanユーティリティもインストールされます。

図3に示すように、コンテナイメージの横にあるPlayボタンをクリックすると、イメージビューからコンテナを起動できます。その後、コンテナのランタイム設定をカスタマイズしたり、イメージの EXPOSE 値(Quarkus ではデフォルトで 8080)に基づいてコンテナの外部ポートをアプリの内部ポートに自動的にマッピングさせたりすることができます。Podmanは、マシン上の別のプロセスが既にそのポートを使用しているかどうかを自動的に把握し、コンテナの外部ポートを別のポートに割り当て直すことができる。これは優れた機能であり、通常システム管理者の領域であるnetstatlsofのようなコマンドを使って、自分のマシンでポートが使われているかどうかを手動で調べなければならないのとは対照的です。

https://developers.redhat.com/sites/default/files/styles/article_floated/public/podman-desktop-start-container_0.png?itok=RTAPDlKV

図3:Podman DesktopのImagesビューにコンテナを起動する「play」ボタンがある

Podman Desktopのその他の機能

Podman Desktop はコンテナを実行するだけではありません。例えば、デバッグやアクセス、あるいは設定を変更するためにコンテナに ssh で入りたいかもしれません。それには、CLI を使って、(例えば podman ps で)コンテナ名を調べて、podman exec -it CONTAINER_ID /bin/bash のようなコマンドを覚えておく必要があります。Podman Desktop では、コンテナビューでコンテナを選択して Terminal タブをクリックするだけです。

https://developers.redhat.com/sites/default/files/styles/article_floated/public/podman-desktop-terminal.png?itok=zQgSlTio

図4:Podman Desktopを使ってコンテナ内のターミナルでコマンドを実行する

同様に、コンテナのログにアクセスしたい場合は、Logsタブをクリックします。また、コンテナの状態を検査したい場合、例えば、使用しているファイルシステムや設定されている環境変数などを確認したい場合は、Inspectをクリックするだけです。

Kubernetes以外でPodを使う

Podman Desktopはその名の通り、コンテナをPodとして実行することもできる。例えば、キャッシュデータベース(Redis や Infinispan)のような別のコンテナを実行し、アプリケーションのコンテナと組み合わせてPodにすることができます。

Kubernetes と Podman Desktop

Podman DesktopからKubernetesインスタンスにコンテナやPodを直接デプロイすることも可能です(図5)。そのためには、Podman Desktopビューの右上にあるロケットアイコンをクリックするだけです。Podman DesktopはKubernetesコンテキストを検出し(kubectl loginなどでKubernetesクラスタにログインしている場合)、コンテナをPodとしてクラスタにデプロイします。

https://developers.redhat.com/sites/default/files/styles/article_floated/public/podman-desktop-deploy-kubernetes.png?itok=02W-YZn1

図5:KubernetesへのデプロイボタンがハイライトされたPodman Desktopのログビュー

Kubernetesクラスタが利用できない場合、Podman Desktopの設定で利用できるKind拡張機能を使ってKubernetes-in-Docker(Kind)クラスタを起動できます。

もう一つの選択肢は、コストのかからない Developer Sandbox for Red Hat OpenShift インスタンスを作成することです。developers.redhat.com/developer-sandbox にアクセスし、Create a free OpenShift Sandbox instance に従ってプロビジョニングできます。これで、コンテナ化されたアプリケーションをデプロイするために使用できる、完全に機能する Kubernetes インスタンスが手に入ります!

今すぐ始める

Javaコンテナの構築と実行は、ここ数年で非常に簡単になりました。Quarkusのようなフレームワークや、Podman Desktop、OpenShiftのようなツールを使うことで、クラウドネイティブの世界に慣れていないJava開発者でも、コンテナを使って簡単に作業を始めることができます。

Quarkusアプリケーションの作成コンテナイメージへのビルドPodman Desktop上での実行を今すぐお試しください。

追加のリソース

関連の記事

関連のコンテンツ

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。