Herokuへのデプロイ
このガイドでは、QuarkusベースのWebアプリケーションをweb-dynoとしてHerokuにデプロイする方法を説明します。
このガイドでは以下をカバーしています:
-
QuarkusのHTTPポートの更新
-
Heroku CLIのインストール
-
アプリケーションのHerokuへのデプロイ
-
アプリケーションをDockerイメージとしてHerokuにデプロイ
-
ネイティブアプリケーションをDockerイメージとしてHerokuにデプロイ
前提条件
このガイドを完成させるには、以下が必要です:
-
ざっと 1 hour for all modalities
-
IDE
-
JDK 11+ がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.8.6
-
使用したい場合は、 Quarkus CLI
-
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が割り当てるポートを意識する必要があります。幸運なことに、そのための動的な設定プロパティがあります。
このガイドでは、 Heroku CLIがインストールされていることを前提としています。
プロジェクトの共通設定
このガイドでは、 入門ガイド で開発されたアプリケーションを入力として使用します。
手元に get-started アプリケーションがあることを確認するか、Git リポジトリをクローンします: git clone https://github.com/quarkusio/quarkus-quickstarts.git
、もしくは アーカイブ をダウンロードしてください。ソリューションは 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 11を必要とするので、まずそれを指定します。
echo "java.runtime.version=11" >> 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 push registry.heroku.com/$APP_NAME/web
heroku container:release web --app $APP_NAME
アプリケーションが実際にコンテナから実行されているかどうか、ログを確認することができますし、確認すべきです。
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\
-Pnative\
-Dquarkus.native.container-build=true
その後、もう一度プッシュし、リリースします。
docker push registry.heroku.com/$APP_NAME/web
heroku container:release web --app $APP_NAME