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

Herokuへのデプロイ

このガイドでは、QuarkusベースのWebアプリケーションをweb-dynoとしてHerokuにデプロイする方法を説明します。

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

  • QuarkusのHTTPポートの更新

  • Heroku CLIのインストール

  • アプリケーションのHerokuへのデプロイ

  • アプリケーションをコンテナイメージとしてHerokuにデプロイ

  • Dockerの使用

  • Podmanの使用

  • ネイティブアプリケーションをコンテナイメージとしてHerokuにデプロイ

前提条件

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

はじめに

Herokuは開発者がアプリケーションの構築、実行、運用をすべてクラウド上で行うことができるPaaS(Platform as a Service)です。Herokuは、Java、Ruby、Node.js、Scala、Clojure、Python、PHP、Goなどの言語をサポートしています。さらに、あらかじめ構築されたコンテナイメージを展開するためのコンテナレジストリも提供しています。

Herokuは、Quarkusのアプリケーションを実行するためにさまざまな方法で使用できます。

  • Herokuの環境で定義されたコンテナ内で動作するプレーンなJavaプログラムとして

  • Quarkusのビルドプロセスで定義されたコンテナ内で実行されるコンテナ化されたJavaプログラムとして

  • Quarkusのビルドプロセスで定義されたコンテナ内で実行されるコンテナ化されたネイティブプログラムとして

この3つのアプローチはいずれも、トラフィックを処理するためにHerokuが割り当てるポートを意識する必要があります。幸運なことに、そのための動的な設定プロパティがあります。

プロジェクトの共通設定

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

手元に get-started アプリケーションがあることを確認するか、Git リポジトリをクローンします: git clone https://github.com/quarkusio/quarkus-quickstarts.git 、もしくは archive をダウンロードしてください。ソリューションは getting-started ディレクトリーにあります。

Herokuではリポジトリの変更を起点にCIを実行し、コードが変更されたときにアプリケーションを再デプロイすることができます。したがって、私たちはすでに有効なリポジトリがある前提で説明します。

また、Heroku CLIが動作していることを確認してください。

heroku --version
heroku login

QuarkusのHTTPポートの準備

Herokuはランダムにポートを選択し、最終的にQuarkusアプリケーションを実行するコンテナに割り当てます。このポートは、 $PORT の環境変数として利用できます。すべての導入シナリオでQuarkusにそれを認識させる最も簡単な方法は、以下の設定を使用することです。

quarkus.http.port=${PORT:8080}

これは次のように読み取れます。"定義済の変数の場合、 $PORT をリッスンする。そうでなければ、通常通り8080でリッスンする" です。以下を実行して、これを application.properties に追加してください。

echo "quarkus.http.port=\${PORT:8080}" >> src/main/resources/application.properties
git commit -am "Configure the HTTP Port."

リポジトリのデプロイとHerokuでのビルド

1つ目は、QuarkusのMavenビルドを使用して、実行可能な "fast-jar "とHerokuのビルドインフラに必要なすべてのライブラリを含む _quarkus-app_アプリケーション構造を作成し、その結果をデプロイするもので、もう1つはローカルビルドプロセスを使用して最適化されたコンテナを作成するものです。

最初のバリエーションでは、アプリケーションのルートディレクトリに 2 つの追加ファイルが必要です:

  • Javaのバージョンを設定する為に system.properties

  • Herokuがアプリケーションを開始する方法を設定するために Procfile

QuarkusにはJDK 17が必要なので、まずそれを指定します:

echo "java.runtime.version=17" >> system.properties
git add system.properties
git commit -am "Configure the Java version for Heroku."

今回はWebアプリケーションをデプロイするので、Heroku Procfile でタイプ web を以下のように設定する必要があります。

echo "web: java \$JAVA_OPTS -jar target/quarkus-app/quarkus-run.jar" >> Procfile
git add Procfile
git commit -am "Add a Procfile."

あなたのアプリケーションは、すでに heroku local web を通して実行可能になっているはずです。

自分のアカウントでアプリケーションを作成し、そこにそのリポジトリをデプロイしてみましょう。

heroku create
git push heroku master
heroku open

アプリケーションには生成された名前があり、ターミナルにはその名前が出力されるはずです。 heroku open は、新しいアプリケーションにアクセスするためにデフォルトのブラウザで開きます。

curlでRESTエンドポイントにアクセスするには、次のように実行します。

APP_NAME=`heroku info | grep  "=== .*" |sed "s/=== //"`
curl $APP_NAME.herokuapp.com/hello

もちろん、Heroku CLIを使ってこのレポジトリをGitHubアカウントに接続することもできますが、これはこのガイドでは対象外です。

コンテナとしてデプロイ

コンテナ全体をプッシュすることの利点は、その内容を完全にコントロールできることであり、GraalVM上で動作するネイティブ実行可能ファイルを持つコンテナをデプロイすることも可能です。

まず、Herokuのコンテナレジストリにログインします。

heroku container:login

Quarkus Mavenプラグインを使ってコンテナイメージを構築するために、プロジェクトにエクステンションを追加する必要があります。

mvn quarkus:add-extension -Dextensions="container-image-docker"
git add pom.xml
git commit -am "Add container-image-docker extension."

これからビルドするイメージは、Herokuのレジストリやデプロイメントと連携するために、適切な名前を付ける必要があります。 heroku info を通して生成された名前を取得し、それを(ローカル)ビルドに渡します。

APP_NAME=`heroku info | grep  "=== .*" |sed "s/=== //"`
mvn clean package\
  -Dquarkus.container-image.build=true\
  -Dquarkus.container-image.group=registry.heroku.com/$APP_NAME\
  -Dquarkus.container-image.name=web\
  -Dquarkus.container-image.tag=latest

イメージのプッシュとリリース

これでイメージをプッシュし、リリース出来ます。

イメージの全レイヤーを転送する必要があるため、最初のプッシュはかなり大きくなります。それ以降のプッシュは小さくなります。

Dockerによるプッシュ

Dockerがインストールされていれば、これらの手順は簡単です:

docker push registry.heroku.com/$APP_NAME/web
heroku container:release web --app $APP_NAME

Podmanを通じたプッシュ

PodmanをDockerの代替として使用したい場合、Heroku CLIはDockerに依存しており、OCIフォーマットをサポートしていないため、いくつかの問題が発生します。しかし、これらの問題を解決する方法があります。

Cannot find docker, please ensure docker is installed.

問題は明らかにheroku-cliがDockerを見つけられないことです。PodmanのcliはDockerと互換性があるので、これを解決するのは簡単です。PodmanからDockerへのシンボリックリンクを作成するだけです:

sudo ln -s $(which podman) /usr/local/bin/docker
Error writing manifest: Error uploading manifest latest to registry.heroku.com/$APP_NAME/web: unsupported

通常のPodmanプッシュ(OCIフォーマット)の代わりに、PodmanとHeroku CLIを通してアプリを希望のフォーマット(v2s2 - Docker Image Manifest Version 2, Schema 2)でプッシュ・リリースするには、回避策を使用する必要があります。また、 skopeo も必要です。

CONTAINER_DIR="target/container-dir"
mkdir $CONTAINER_DIR
podman push --format=v2s2 "registry.heroku.com/$APP_NAME/web" dir:$CONTAINER_DIR
skopeo --debug copy dir:$CONTAINER_DIR "docker://registry.heroku.com/$APP_NAME/web:latest"
heroku container:release web --app "$APP_NAME"
rm -rf $CONTAINER_DIR

ログの確認

アプリケーションが実際にコンテナから実行されているかどうか、ログを確認することができますし、確認すべきです。

heroku logs --app $APP_NAME --tail

コンテナ内にネイティブ・アプリケーションとしてデプロイ

アプリをコンテナとしてデプロイする際の最大のメリットは、ネイティブにコンパイルされたアプリを使ってコンテナをデプロイすることです。なぜか?なぜなら、Herokuは着信トラフィックがないときにアプリケーションを停止またはスリープさせるからです。ネイティブ・アプリケーションは、スリープ状態からより早く目覚めます。

プロセスはほとんど同じです。ここでは、ローカルコンテナ内でネイティブイメージをコンパイルすることを選択し、ローカルにGraalVMをインストールする必要がないようにしています。

APP_NAME=`heroku info | grep  "=== .*" |sed "s/=== //"`
mvn clean package\
  -Dquarkus.container-image.build=true\
  -Dquarkus.container-image.group=registry.heroku.com/$APP_NAME\
  -Dquarkus.container-image.name=web\
  -Dquarkus.container-image.tag=latest\
  -Dnative\
  -Dquarkus.native.container-build=true

その後、DockerまたはPodman(上記参照)を使って再度プッシュ・リリースし、ログを確認してください。

関連コンテンツ