Heroku スターターガイド (Scala および Play)
はじめに
このチュートリアルを完了して、サンプル Scala アプリを Heroku にデプロイします。
このチュートリアルでは、以下が用意されていることを前提としています。
- 確認済みの Heroku アカウント
- OpenJDK 17 (またはそれ以降) がインストールされている
- sbt がインストールされている
- Postgres がインストールされている
- Eco dyno プランのサブスクリプション (推奨)
dyno とデータベースを使用してこのチュートリアルを完了した場合、使用量のカウントに入ります。低料金プランを使用してこのチュートリアルを完了することをお勧めします。資格のある学生の皆様は、新しい Heroku for GitHub Students プログラムを通じてプラットフォームクレジットを申請できます。
設定する
Heroku CLI には、一般によく使われている Git というバージョン管理システムが必要です。Git がインストールされていない場合は、先に進む前に次の手順を完了してください。
Heroku Command Line Interface (CLI) をインストールします。CLI は、アプリケーションの管理やスケール、アドオンのプロビジョニング、ログの表示、アプリケーションのローカル実行に使用できます。
ご使用のプラットフォーム用のインストーラをダウンロードし、実行してください。
$ brew tap heroku/brew && brew install heroku
インストール後、ターミナルで heroku
コマンドを使用できます。
Heroku CLI にログインするには、heroku login
コマンドを使用します。
$ heroku login
heroku: Press any key to open up the browser to login or q to exit
› Warning: If browser does not open, visit
› https://cli-auth.heroku.com/auth/browser/***
heroku: Waiting for login...
Logging in... done
Logged in as me@example.com
このコマンドにより、Web ブラウザで認証を完了するための Heroku ログインページが開きます。ブラウザですでに Heroku にログインしている場合は、ページに表示されているLog in
(ログイン) ボタンをクリックします。
heroku
と git
のコマンドが両方とも正しく機能するには、この認証が必要です。
外部の HTTP/HTTPS サービスへの接続にプロキシが必要なファイアウォールを使っている場合は、heroku
コマンドを実行する前に、ローカルの開発環境で HTTP_PROXY
または HTTPS_PROXY
環境変数を設定してください。
アプリを準備する
Heroku をはじめて使う場合は、 Heroku が提供するサンプルアプリケーションを使ってこのチュートリアルを行うことをお勧めします。
デプロイするアプリケーションを用意してある場合は、 「Heroku のデプロイ用にコードベースを準備する」を参照してください。
ローカルのコマンドシェルまたはターミナルで次のコマンドを実行して、サンプルアプリのローカルコピーを作成します。
$ git clone https://github.com/heroku/scala-getting-started
$ cd scala-getting-started
この正常な Git リポジトリには、サンプル Scala アプリケーションが格納されています。これには Scala のビルドツールである sbt
が使用する build.sbt
ファイルが含まれています。
アプリを作成する
Eco にサブスクライブしている場合、アプリではデフォルトで Eco dyno が使用されます。それ以外の場合は、デフォルトで Basic dyno が使用されます。Eco dyno プランは、アカウント内のすべての Eco dyno で共有されます。これは、多数の小さいアプリを Heroku にデプロイする予定がある場合にお勧めします。詳細は、こちらを参照してください。資格のある学生の皆様は、Heroku for GitHub Students プログラムを通じてプラットフォームクレジットを申請できます。
Heroku でソースコードを受け取る準備をするには、アプリを作成します。
$ heroku create
Creating app... done, ⬢ peaceful-inlet-84135
http://peaceful-inlet-84135.herokuapp.com/ | https://git.heroku.com/peaceful-inlet-84135.git
アプリを作成すると、heroku
という名前の Git リモートリポジトリも作成され、ローカルの Git リポジトリと関連付けられます。Git リモートは、他のサーバー上で稼働するリポジトリのバージョンです。アプリに関連付けられた、Heroku でホストされる特別なリモートにコードをプッシュすることにより、アプリをデプロイします。
Heroku によってランダムなアプリ名 (このケースでは peaceful-inlet-84135
) が生成されます。独自のアプリ名を指定できます。
Procfile を定義する
Procfile は、アプリケーションのルートディレクトリにあるテキストファイルです。このファイルを使って、アプリの起動時に実行するコマンドを明示的に宣言します。
サンプルアプリの Procfile
は、次のようになっています。
web: target/universal/stage/bin/scala-getting-started -Dhttp.port=${PORT}
この Procfile では、単一のプロセスタイプの web
と、その実行に必要なコマンドを宣言しています。 ここでは、web
という名前が重要です。 これは、このプロセスタイプを Heroku の HTTP ルーティングスタックにアタッチし、デプロイ後に Web トラフィックを受信することを宣言しています。
Procfile には追加のプロセスタイプを含めることができます。 たとえば、キューからアイテムを取り出して処理するバックグラウンドワーカープロセスを宣言できます。
データベースをプロビジョニングする
サンプルアプリにはデータベースが必要です。Elements Marketplace から入手可能なアドオンの 1 つである Heroku Postgres データベースをプロビジョニングします。アドオンは、ログ記録、モニタリング、データベースなど、アプリケーションですぐに使える追加サービスを提供するクラウドサービスです。
essential-0
Postgres のサイズのコストは月額 5 ドルで、分単位で課金されます。このガイドが完了したら、データベースを削除して、コストを最小限に抑えます。
$ heroku addons:create heroku-postgresql:essential-0
Creating heroku-postgresql:essential-0 on ⬢ peaceful-inlet-84135... ~$0.007/hour (max $5/month)
Database should be available soon
postgresql-fitted-70383 is being created in the background. The app will restart when complete...
Use heroku addons:info postgresql-fitted-70383 to check creation progress
Use heroku addons:docs heroku-postgresql to view documentation
Heroku アプリで Postgres データベースにアクセスできるようになりました。DATABASE_URL
環境変数には資格情報が格納されます。Heroku では、JDBC_DATABASE_URL
環境変数を Scala アプリケーションで自動的に使用できるようにしています。これには、DATABASE_URL
の JDBC 互換バージョンが格納されます。
addons
コマンドを使用して、プロビジョニングされたすべてのアドオンを確認できます。
$ heroku addons
Add-on Plan Price State
─────────────────────────────────────────── ─────────── ──────── ───────
heroku-postgresql (postgresql-fitted-70383) essential-0 $5/month created
└─ as DATABASE
アプリをデプロイする
コードをデプロイします。このコマンドは、サンプルリポジトリの main
ブランチを heroku
リモートにプッシュし、次に Heroku にデプロイします。
$ git push heroku main
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-22 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Play 2.x - Scala app detected
remote: -----> Installing OpenJDK 17... done
remote: -----> Priming Ivy cache... done
remote: -----> Running: sbt compile stage
remote: Downloading sbt launcher for 1.7.2:
remote: From https://repo1.maven.org/maven2/org/scala-sbt/sbt-launch/1.7.2/sbt-launch-1.7.2.jar
remote: To /tmp/scala_buildpack_build_dir/.sbt_home/launchers/1.7.2/sbt-launch.jar
remote: Downloading sbt launcher 1.7.2 md5 hash:
remote: From https://repo1.maven.org/maven2/org/scala-sbt/sbt-launch/1.7.2/sbt-launch-1.7.2.jar.md5
remote: To /tmp/scala_buildpack_build_dir/.sbt_home/launchers/1.7.2/sbt-launch.jar.md5
remote: /tmp/scala_buildpack_build_dir/.sbt_home/launchers/1.7.2/sbt-launch.jar: OK
remote: [info] [launcher] getting org.scala-sbt sbt 1.7.2 (this may take some time)...
remote: [info] [launcher] getting Scala 2.12.16 (for sbt)...
remote: [info] welcome to sbt 1.7.2 (Azul Systems, Inc. Java 17.0.6)
remote: [info] loading global plugins from /tmp/scala_buildpack_build_dir/.sbt_home/plugins
remote: [info] compiling 1 Scala source to /tmp/scala_buildpack_build_dir/.sbt_home/plugins/target/scala-2.12/sbt-1.0/classes ...
remote: [info] Non-compiled module 'compiler-bridge_2.12' for Scala 2.12.16. Compiling...
remote: [info] Compilation completed in 15.389s.
remote: [info] done compiling
remote: [info] loading settings for project scala_buildpack_build_dir-build from plugins.sbt ...
remote: [info] loading project definition from /tmp/scala_buildpack_build_dir/project
remote: [info] loading settings for project root from build.sbt ...
remote: [info] __ __
remote: [info] \ \ ____ / /____ _ __ __
remote: [info] \ \ / __ \ / // __ `// / / /
remote: [info] / / / /_/ // // /_/ // /_/ /
remote: [info] /_/ / .___//_/ \__,_/ \__, /
remote: [info] /_/ /____/
remote: [info]
remote: [info] Version 2.8.19 running Java 17.0.6
remote: [info]
remote: [info] Play is run entirely by the community. Please consider contributing and/or donating:
remote: [info] https://www.playframework.com/sponsors
remote: [info]
remote: [info] Running Play on Java 17 is experimental. Tweaks are necessary:
remote: [info] https://github.com/playframework/playframework/releases/2.8.15
remote: [info]
remote: [info] Executing in batch mode. For better performance use sbt's shell
remote: [info] compiling 8 Scala sources and 1 Java source to /tmp/scala_buildpack_build_dir/target/scala-2.13/classes ...
remote: [info] Non-compiled module 'compiler-bridge_2.13' for Scala 2.13.10. Compiling...
remote: [info] Compilation completed in 15.043s.
remote: [info] done compiling
remote: [success] Total time: 23 s, completed Apr 5, 2023, 9:00:57 AM
remote: [info] Wrote /tmp/scala_buildpack_build_dir/target/scala-2.13/scala-getting-started_2.13-1.0-SNAPSHOT.pom
remote: [info] Main Scala API documentation to /tmp/scala_buildpack_build_dir/target/scala-2.13/api...
remote: [info] Main Scala API documentation successful.
remote: [success] Total time: 5 s, completed Apr 5, 2023, 9:01:01 AM
remote: -----> Collecting dependency information
remote: -----> Dropping ivy cache from the slug
remote: -----> Dropping sbt boot dir from the slug
remote: -----> Dropping sbt cache dir from the slug
remote: -----> Dropping compilation artifacts from the slug
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 108.2M
remote: -----> Launching...
remote: Released v4
remote: https://peaceful-inlet-84135.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/peaceful-inlet-84135.git
* [new branch] main -> main
Eco にサブスクライブしている場合、アプリではデフォルトで Eco dyno が使用されます。dyno は、Procfile
で指定されているコマンドを実行する軽量の Linux コンテナです。デプロイ後に、1 つの web
dyno がアプリを実行していることを確認します。実行されている dyno の数を確認するには、heroku ps
コマンドを使います。
$ heroku ps
Eco dyno hours quota remaining this month: 1000h 0m (100%)
Eco dyno usage for this app: 0h 0m (0%)
For more information on Eco dyno hours, see:
https://devcenter.heroku.com/articles/eco-dyno-hours
=== web (Eco): target/universal/stage/bin/scala-getting-started -Dhttp.port=${PORT} (1)
web.1: up 2023/03/09 17:00:28 +0100 (~ 1m ago)
実行中の web
dyno がリクエストに応答します。ログに示されている URL でアプリにアクセスします。次のショートカットを使うと、簡単に Web サイトを開くことができます。
$ heroku open
Eco dyno プランは、アカウントのすべての Eco dyno 間で共有され、多数の小さなアプリを Heroku にデプロイする場合にお勧めします。Eco dyno は 30 分間トラフィックを何も受信しないとスリープします。 このスリープ動作により、スリープ解除した最初のリクエストで数秒の遅延が発生します。Eco dyno は、月ごとに割り当てられるアカウント別の Eco dyno 時間を消費します。割り当て時間が残っている限り、アプリは稼働し続けます。
dyno がスリープしないようにするには、「dyno タイプ」で紹介されている Basic または Professional の dyno タイプにアップグレードしてください。
アプリをスケールする
Heroku でアプリケーションを水平方向にスケーリングすることは、実行中の dyno の数を変更することを意味します。
Web dyno の数を 0 にスケールしてみます。
$ heroku ps:scale web=0
ブラウザを更新するか、heroku open
を実行して、もう一度アプリにアクセスします。リクエストに応答できる Web dyno がアプリにないので、エラーメッセージが表示されます。
もう一度スケールしてみましょう。
$ heroku ps:scale web=1
大規模な dyno にアップグレードすることによって、垂直方向のスケーリングを行うこともできます。詳細は、「dyno タイプ」および「Dyno formation のスケーリング」を参照してください。
ログを表示する
Heroku では、すべてのアプリと Heroku のコンポーネントの出力ストリームから集約した時系列イベントのストリームとして、ログが扱われます。Heroku は、すべてのイベントに単一のストリームを提供します。
実行中のアプリに関する情報を表示するには、ログコマンドの 1 つである、heroku logs --tail
を使います。
$ heroku logs --tail
2023-03-09T17:01:33.946880+00:00 heroku[web.1]: Starting process with command `target/universal/stage/bin/scala-getting-started -Dhttp.port=${PORT}`
2023-03-09T17:01:34.777255+00:00 app[web.1]: Setting JAVA_TOOL_OPTIONS defaults based on dyno size. Custom settings will override them.
2023-03-09T17:01:34.865577+00:00 app[web.1]: Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8
2023-03-09T17:01:36.959678+00:00 app[web.1]: 2023-03-09 17:01:36 WARN play.api.http.HttpConfiguration
2023-03-09T17:01:37.096800+00:00 app[web.1]: 2023-03-09 17:01:37 INFO play.api.Play Application started (Prod) (no global state)
2023-03-09T17:01:37.700798+00:00 app[web.1]: 2023-03-09 17:01:37 INFO play.core.server.AkkaHttpServer Listening for HTTP on /[0:0:0:0:0:0:0:0]:7707
2023-03-09T17:01:38.191846+00:00 heroku[web.1]: State changed from starting to up
2023-03-09T17:01:56.000000+00:00 app[api]: Build succeeded
2023-03-09T17:04:55.627566+00:00 heroku[router]: at=info method=GET path="/" host=peaceful-inlet-84135.herokuapp.com request_id=f7b88a86-0e62-49f8-b37a-a083a558ed0e fwd="85.222.134.3" dyno=web.1 connect=0ms service=196ms status=200 bytes=9081 protocol=https
2023-03-09T17:04:55.932796+00:00 heroku[router]: at=info method=GET path="/assets/stylesheets/main.css" host=peaceful-inlet-84135.herokuapp.com request_id=af71979c-ea8b-4486-af07-0248d59fc5d5 fwd="85.222.134.3" dyno=web.1 connect=0ms service=95ms status=200 bytes=1115 protocol=https
2023-03-09T17:04:55.934057+00:00 heroku[router]: at=info method=GET path="/assets/images/lang-logo.png" host=peaceful-inlet-84135.herokuapp.com request_id=893a88af-6de6-40fa-888b-16488831aef7 fwd="85.222.134.3" dyno=web.1 connect=0ms service=85ms status=200 bytes=1587 protocol=https
2023-03-09T17:04:56.139535+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=peaceful-inlet-84135.herokuapp.com request_id=8b1dccd0-15b4-47f2-97d0-2df49c09a94b fwd="85.222.134.3" dyno=web.1 connect=0ms service=23ms status=404 bytes=1501 protocol=https
さらに他の生成されたログメッセージを表示するには、まずブラウザでアプリケーションにアクセスします。
ログのストリーム出力を停止するには、Control+C
を押します。
ログ記録アドオンをプロビジョニングする
アドオンは、アプリケーションですぐに使える追加サービスを提供するサードパーティのクラウドサービスです。永続性、ログ記録、モニタリングなど、さまざまなアドオンがあります。
Heroku では、デフォルトで 1500 行のアプリケーションログが記録されますが、完全なログストリームはサービスとして提供されています。複数のアドオンプロバイダーが、ログの永続化、検索、メールや SMS 通知などの機能を提供するログサービスを用意しています。
このステップでは、このようなログ関連アドオンの 1 つである、Papertrail をプロビジョニングします。
Papertrail ログ記録アドオンをプロビジョニングします。
$ heroku addons:create papertrail
Creating papertrail on ⬢ peaceful-inlet-84135... free
Welcome to Papertrail. Questions and ideas are welcome (technicalsupport@solarwinds.com). Happy logging!
Created papertrail-slippery-84785 as PAPERTRAIL_API_TOKEN
Use heroku addons:docs papertrail to view documentation
このアドオンが動作していることを確認するため、アプリケーションの Heroku URL に数回アクセスします。アクセスするたびにログメッセージが生成され、Papertrail のアドオンに送られます。 Papertrail のコンソールにアクセスし、ログメッセージを確認します。
$ heroku addons:open papertrail
ブラウザで Papertrail の Web コンソールが開き、最新のログイベントが表示されます。このインターフェースでは、検索したり通知を設定したりできます。
データベースを使用する
Heroku には Postgres と Redis のマネージドデータサービスがあり、add-on marketplace には MongoDB や MySQL などの追加のデータサービスがあります。
heroku addons
コマンドを使用すると、アプリに対してプロビジョニングされるデータベースの概要が示されます。
$ heroku addons
Add-on Plan Price State
─────────────────────────────────────────── ─────────── ──────── ───────
heroku-postgresql (postgresql-fitted-70383) essential-0 $5/month created
└─ as DATABASE
papertrail (papertrail-slippery-84785) choklad free created
└─ as PAPERTRAIL
アプリの環境設定を一覧表示すると、アプリがデータベースに接続するときに使用する URL (DATABASE_URL
) が表示されます。
$ heroku config
=== peaceful-inlet-84135 Config Vars
DATABASE_URL: postgres://avhrhofbiyvpct:3ab23026d0fc225bde4544cedabc356904980e6a02a2418ca44d7fd19dad8e03@ec2-23-21-4-7.compute-1.amazonaws.com:5432/d8e8ojni26668k
PAPERTRAIL_API_TOKEN: ChtIUu9fHbij1cBn7y6z
heroku pg
コマンドを使用すると、アプリの Heroku Postgres データベースについて、より詳細な情報が表示されます。
$ heroku pg
=== DATABASE_URL
Plan: Essential 0
Status: Available
Connections: 0/20
PG Version: 15.5
Created: 2024-05-01 16:00 UTC
Data Size: 8.6 MB/1.00 GB (0.84%) (In compliance)
Tables: 0
Fork/Follow: Unsupported
Rollback: Unsupported
Continuous Protection: Off
Add-on: postgresql-fitted-70383
アプリに対してこのコマンドを実行すると、アプリに essential-0
Postgres データベースがあり、Postgres 15.5 を実行していて、テーブルがないことがわかります。
デプロイしたサンプルアプリにはデータベース機能が備わっています。これにはアプリの URL に /database
パスを追加することでアクセスできます。
$ heroku open /database
次のように表示されます。
Read from DB: 2023-03-09 16:58:55.816605
Read from DB: 2023-03-09 16:58:56.728701
Read from DB: 2023-03-09 16:58:57.064755
ローカル環境に Postgres がインストールされているという前提で、heroku pg:psql
コマンドを使ってリモートデータベースに接続し、すべての行を表示します。
$ heroku pg:psql
--> Connecting to postgresql-fitted-70383
psql (15.2, server 14.7 (Ubuntu 14.7-1.pgdg20.04+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
peaceful-inlet-84135::DATABASE=> SELECT * FROM ticks;
tick
----------------------------
2023-03-09 16:58:55.816605
2023-03-09 16:58:56.728701
2023-03-09 16:58:57.064755
(3 rows)
peaceful-inlet-84135::DATABASE=> \q
次の情報は、サンプルアプリでデータベース機能を実装する方法を示しています。このステップで、サンプルアプリのコードを変更しないでください
サンプルアプリのコードは、次のようになっています。
def db(): Action[AnyContent] = Action { implicit request: Request[AnyContent] =>
// In this getting started app, we don't use a custom execution context to keep the code and configuration simple.
// For real-world apps, consult the Play documentation on how to configure custom contexts and how to use them:
// https://www.playframework.com/documentation/2.8.19/AccessingAnSQLDatabase#Using-a-CustomExecutionContext
database.withConnection { connection =>
val statement = connection.createStatement()
statement.executeUpdate("CREATE TABLE IF NOT EXISTS ticks (tick timestamp)")
statement.executeUpdate("INSERT INTO ticks VALUES (now())")
val output = new StringBuilder();
val resultSet = statement.executeQuery("SELECT tick FROM ticks")
while (resultSet.next()) {
output.append("Read from DB: " + resultSet.getTimestamp("tick") + "\n")
}
Ok(output.toString())
}
}
db
メソッドでは、/database
ルートを使用してアプリにアクセスしたときに、行が tick
テーブルに追加されます。次に、出力に表示するすべての行を返します。
サンプルアプリのコードに示す Database
は、Play フレームワークによって自動的に設定および挿入されます。これはデータベース接続設定のための conf/application.conf
ファイル内の値を参照します。
サンプルアプリでは、データベースへの接続のプールを設定するために、db.default.url
が JDBC_DATABASE_URL
環境変数内の値に設定されています。
db.default.url = ${JDBC_DATABASE_URL}
アプリに自動的に追加される公式の Heroku Scala buildpack では、dyno の起動時にこの JDBC_DATABASE_URL
環境変数が設定されます。この変数は動的であり、heroku config
を実行しても環境設定の一覧に表示されません。次のコマンドを実行すると表示できます。
$ heroku run echo \$JDBC_DATABASE_URL
詳細は、「Heroku PostgreSQL」を参照してください。Redis または他のデータアドオンも、heroku addons:create
によってインストールできます。
ローカル環境を準備する
アプリをローカルで実行できるようにする前に、アプリの依存関係をインストールする必要があります。
ローカルディレクトリで sbt stage
を実行します。このコマンドにより依存関係がインストールされ、アプリをローカルで実行できるようシステムが準備されます。
$ sbt stage
...
[info] Wrote /Users/example-user/projects/scala-getting-started/target/scala-2.13/scala-getting-started_2.13-1.0-SNAPSHOT.pom
[info] Main Scala API documentation to /Users/example-user/projects/scala-getting-started/target/scala-2.13/api...
[info] Main Scala API documentation successful.
[success] Total time: 3 s, completed 9 Mar 2023, 17:48:51
ステージング後、アプリをローカルで実行できますが、まだ Postgres データベースが必要です。ローカルの Postgres データベースを作成し、ローカルの .env
ファイルを更新します。
アプリをローカルで実行するために使用される heroku local
により、アプリのルートディレクトリにある .env
ファイルに基づき環境が自動的に設定されます。JDBC_DATABASE_URL
環境変数にローカルの Postgres データベースの接続文字列を設定します。
JDBC_DATABASE_URL=jdbc:postgresql://localhost:5432/scala_database_name
これで、アプリを実行してデータベースに接続するためのローカル環境の準備ができました。
アプリをローカルで実行する
アプリをローカルで実行する前に sbt stage
がすでに実行されていることを確認します。
heroku local
CLI コマンドを使用して、アプリケーションをローカルで開始します。
$ heroku local --port 5001
...
5:26:58 AM web.1 | 2023-03-09 17:58:43 INFO play.api.db.DefaultDBApi Database [default] initialized
5:26:58 AM web.1 | 2023-03-09 17:58:43 INFO play.api.db.HikariCPConnectionPool Creating Pool for datasource 'default'
5:26:58 AM web.1 | 2023-03-09 17:58:43 INFO play.api.Play Application started (Prod) (no global state)
5:26:58 AM web.1 | 2023-03-09 17:58:44 INFO play.core.server.AkkaHttpServer Listening for HTTP on /[0:0:0:0:0:0:0:0]:5001
Heroku プラットフォームと同じように、heroku local
も Procfile
を確認して実行するコマンドを判断します。
アプリがローカルで実行していることを確認するには、Web ブラウザで「http://localhost:5001」を開きます
アプリの /database
ルートにローカルでアクセスする必要がある場合、URL にアクセスする前にローカルの Postgres データベースが実行中であることを確認してください。
アプリのローカルでの実行を停止するには、ターミナルウィンドウに戻り、Control+C
を押して終了します。
ローカルの変更をプッシュする
このステップでは、ローカルでアプリに変更を加え、変更を Heroku にデプロイする方法について学びます。
build.sbt
を編集し、libraryDependencies
に次のコードを追加して、jscience
の依存関係を追加します。
"org.jscience" % "jscience" % "4.3.1"
app/controllers/Application.scala
ファイル内で、ライブラリに対する次のインポートステートメントを追加します。
import org.jscience.physics.amount.Amount
import org.jscience.physics.model.RelativisticModel
import javax.measure.unit.SI
次の convert
メソッドを Application.scala
に追加します。
def convert(): Action[AnyContent] = Action { implicit request: Request[AnyContent] =>
RelativisticModel.select()
val energy = Amount.valueOf("12 GeV");
Ok("E=mc^2: " + energy + " = " + energy.to(SI.KILOGRAM))
}
conf/routes
に新しいアクションのルートを追加します。
GET /convert controllers.Application.convert()
Application.scala
の最終的なソースコードはこのようになります。変更内容が同じようになっていることを確認します。ローカルで行ったすべての変更の差分はこちらです。
ローカルで変更をテストします。
$ sbt stage
...
[info] Wrote /Users/example-user/projects/scala-getting-started/target/scala-2.13/scala-getting-started_2.13-1.0-SNAPSHOT.pom
[success] Total time: 1 s, completed 9 Mar 2023, 18:05:12
$ heroku local --port 5001
...
6:05:29 PM web.1 | 2023-03-09 18:05:15 INFO play.api.db.DefaultDBApi Database [default] initialized
6:05:29 PM web.1 | 2023-03-09 18:05:15 INFO play.api.db.HikariCPConnectionPool Creating Pool for datasource 'default'
6:05:29 PM web.1 | 2023-03-09 18:05:15 INFO play.api.Play Application started (Prod) (no global state)
6:05:29 PM web.1 | 2023-03-09 18:05:15 INFO play.core.server.AkkaHttpServer Listening for HTTP on /[0:0:0:0:0:0:0:0]:5001
http://localhost:5001/convert でアプリケーションの /convert
パスにアクセスすると、科学的な換算式が表示されます。
E=mc^2: 12 GeV = (2.139194076302506E-26 ± 1.4E-42) kg
テスト後に、変更内容をデプロイします。Heroku のデプロイは、ほとんどの場合、このパターンで行います。まず、git add
コマンドを使用して、編集したファイルをコミットのためにステージングします。
$ git add .
次に、変更内容をリポジトリにコミットします。
$ git commit -m "Add convert endpoint"
前と同じ方法でデプロイします。
$ git push heroku main
最後に、そのルートでブラウザを開いて、更新されたコードが正しくデプロイされていることを確認します。
$ heroku open /convert
環境設定を定義する
Heroku では、暗号鍵や外部リソースのアドレスなどのデータを環境設定に保存することで、アプリの設定を外部に置くことができます。
ランタイムでは、環境設定は環境変数としてアプリに提供されます。例として、Application.scala
を編集し、環境変数 ENERGY
から energy の値を取得するメソッドを追加します。
app/controllers/Application.scala
ファイル内で、convert
メソッドを変更します。
def convert(): Action[AnyContent] = Action { implicit request: Request[AnyContent] =>
RelativisticModel.select()
Ok(sys.env.get("ENERGY")
.map(Amount.valueOf)
.map(energy => "E=mc^2: " + energy + " = " + energy.to(SI.KILOGRAM))
.getOrElse("ENERGY environment variable is not set!"))
}
sbt stage
を実行して、この変更を統合するようアプリを再コンパイルします。
heroku local
は、アプリのルートディレクトリにある .env
ファイルに基づいて、ローカル環境を自動的に設定します。サンプルアプリには、すでに以下の内容の .env
ファイルがあります。
ENERGY=20 GeV
アプリのローカル実行 ステップで設定した場合、ローカルの .env
ファイルには、JDBC_DATABASE_URL
変数も含まれています。
.env
ファイルをバージョン管理にコミットしないでください。多くの場合、このファイルには機密性の高い資格情報が入っているためです。.env
は、リポジトリの .gitignore
ファイルに入れてください。サンプルアプリのリポジトリには、このチュートリアルステップの例としての .env
ファイルのみを格納します。
heroku local --port 5001
でアプリを実行して http://localhost:5001/convert にアクセスすると、換算値として 20 GeV が表示されます。
ローカルで期待通り機能することがわかったので、Heroku 上で実行するアプリの環境設定としてこの変数を設定します。以下を実行します。
$ heroku config:set ENERGY="20 GeV"
Setting ENERGY and restarting ⬢ peaceful-inlet-84135... done, v9
ENERGY: 20 GeV
heroku config
を使用してアプリの環境設定を表示し、正しく設定されたことを確認します。
$ heroku config
=== peaceful-inlet-84135 Config Vars
DATABASE_URL: postgres://avhrhofbiyvpct:3ab23026d0fc225bde4544cedabc356904980e6a02a2418ca44d7fd19dad8e03@ec2-23-21-4-7.compute-1.amazonaws.com:5432/d8e8ojni26668k
ENERGY: 20 GeV
PAPERTRAIL_API_TOKEN: ChtIUu9fHbij1cBn7y6z
ローカルでの変更内容を Heroku にデプロイし、/convert
ルートにアクセスして動作中の変更内容を確認します。
$ git add .
$ git commit -m "Use ENERGY environment variable"
$ git push heroku main
$ heroku open /convert
One-off Dyno を開始する
heroku run
コマンドを使用して、One-off dyno 内のアプリでメンテナンスや管理のタスクを実行できます。このコマンドでは、アプリの環境で試行錯誤するためにローカルのターミナルにアタッチされた REPL プロセスや、デプロイされたアプリケーションコードを起動することもできます。
$ heroku run java -version
Running java -version on ⬢ peaceful-inlet-84135... up, run.4406 (Eco)
openjdk version "17.0.6" 2023-01-17 LTS
OpenJDK Runtime Environment Zulu17.40+19-CA (build 17.0.6+10-LTS)
OpenJDK 64-Bit Server VM Zulu17.40+19-CA (build 17.0.6+10-LTS, mixed mode, sharing)
Error connecting to process
というエラーが表示された場合は、ファイアウォールを設定します。
必ず exit
と入力してシェルを閉じ、dyno を終了してください。
次のステップ
これで完了です。ここまでは、アプリのデプロイ、アプリの設定変更、アプリのスケール、ログの表示、アドオンのアタッチ、ローカルでの実行方法を説明しました。
引き続き Heroku を活用するためにお勧めするリソースを以下に紹介します。
- 「Heroku の仕組み」では、アプリの作成、設定、デプロイ、および実行時に必要な技術的な概念の概要を紹介しています。
- Scala カテゴリでは、Scala アプリの開発とデプロイに関する詳細を確認できます。
- 「デプロイカテゴリ」では、デプロイを効率的かつ簡単に行うことができるようにする、多くの強力な統合や機能を紹介しています。
コストを抑制するために、チュートリアルを完了したらすぐにサンプルアプリを削除し、データベースも削除してください。
アプリとアドオンを削除する
アカウントからアプリとデータベースを削除します。使用したリソースに対してのみ課金されます。
この操作により、アドオンとデータベースに保存されたすべてのデータが削除されます。
$ heroku addons:destroy heroku-postgresql
▸ WARNING: Destructive Action
▸ This command will affect the app peaceful-inlet-84135
▸ To proceed, type peaceful-inlet-84135 or re-run this command with
▸ --confirm peaceful-inlet-84135
>
この操作により、アプリケーションが完全に削除されます。
$ heroku apps:destroy
▸ WARNING: This will delete ⬢ peaceful-inlet-84135 including all add-ons.
▸ To proceed, type peaceful-inlet-84135 or re-run this command with
▸ --confirm peaceful-inlet-84135
>
以下のコマンドによって、アドオンとアプリが消去されたことを確認できます。
$ heroku addons --all
$ heroku apps --all