Heroku スターターガイド (Node.js)
はじめに
このチュートリアルでは、Node.js アプリを Heroku にすばやくデプロイする方法について説明します。
このチュートリアルでは、以下が用意されていることを前提としています。
- 確認済みの Heroku アカウント
- ローカルにインストールされた Node.js および npm
- 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 Command Line Interface (CLI) のその他のインストールオプションについては こちら を参照してください。
インストールが完了したら、ターミナルで 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
環境変数を設定できます。
手順を進める前に、前提条件の項目が正しくインストールされていることを確認します。次の各コマンドを実行し、インストールしたバージョンが表示されることを確認します(実際のバージョンは以下の例と異なる可能性があります)。バージョン情報が表示されない場合は、前提条件の項目をインストールしてください。
アプリの依存関係を宣言してそれ以降の手順を実行するには、このローカル設定を完了する必要があります。
このチュートリアルでは、Node のバージョン 18 以降が必要です。
$ node --version
v20.9.0
Node と一緒にインストールされる npm
がインストールされていることを確認します。インストールされていない場合は、より新しいバージョンの Node をインストールしてください。
$ npm --version
10.1.0
git
がインストールされていることを確認します。 インストールされていない場合は、インストールして、もう一度テストしてください。
$ git --version
git version 2.42.0
アプリを準備する
このステップでは、Heroku にデプロイできるサンプルアプリケーションを準備します。
Heroku を初めて使う場合は、Heroku が提供するサンプルアプリケーションを使ってこのチュートリアルを行うことをお勧めします。
ただし、デプロイする既存のアプリケーションを用意してある場合は、この記事を参照して、Heroku へのデプロイ用にアプリケーションを準備する方法を確認してください。
Heroku にデプロイするサンプルアプリケーションのローカルバージョンをクローンするには、ローカルのコマンドシェルまたはターミナルで次のコマンドを実行します。
$ git clone https://github.com/heroku/node-js-getting-started.git
$ cd node-js-getting-started
これで、シンプルなアプリケーションと、Node の依存関係マネージャが使用する package.json
ファイルを格納した、正常な Git リポジトリを準備できました。
アプリをデプロイする
このステップでは、アプリを Heroku にデプロイします。
dyno を使用してこのチュートリアルを完了した場合、使用量のカウントに入ります。コストを抑制するために、完了したらすぐにアプリを削除してください。
Eco にサブスクライブしている場合、アプリではデフォルトで Eco dyno が使用されます。それ以外の場合は、デフォルトで Basic dyno が使用されます。多数の小さなアプリを Heroku にデプロイする場合は、アカウントのすべての Eco dyno 間で共有される Eco dyno プランをお勧めします。詳細は、こちらを参照してください。資格のある学生の皆様は、Heroku for GitHub Students プログラムを通じてプラットフォームクレジットを申請できます。
Heroku でアプリを作成すると、Heroku でソースコードを受け取ることができるよう準備できます。
$ heroku create
Creating app... done, ⬢ shrouded-anchorage-35377
https://shrouded-anchorage-35377.herokuapp.com/ | https://git.heroku.com/shrouded-anchorage-35377.git
アプリを作成すると、heroku
という名前の Git リモートリポジトリも作成されます。これは、ローカルの Git リポジトリと関連付けられます。
Heroku によってランダムなアプリ名 (このケースでは shrouded-anchorage-35377
) が生成されます。または、パラメータを渡して独自のアプリ名を指定できます。
コードをデプロイします。
$ git push heroku main
Enumerating objects: 554, done.
Counting objects: 100% (554/554), done.
Delta compression using up to 20 threads
Compressing objects: 100% (412/412), done.
Writing objects: 100% (554/554), 248.74 KiB | 124.37 MiB/s, done.
Total 554 (delta 109), reused 548 (delta 106), pack-reused 0
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: -----> Node.js app detected
remote:
remote: -----> Creating runtime environment
remote:
remote: NPM_CONFIG_LOGLEVEL=error
remote: NODE_VERBOSE=false
remote: NODE_ENV=production
remote: NODE_MODULES_CACHE=true
remote:
remote: -----> Installing binaries
remote: engines.node (package.json): 20.x
remote: engines.npm (package.json): unspecified (use default)
remote:
remote: Resolving node version 20.x...
remote: Downloading and installing node 20.9.0...
remote: Using default npm version: 10.1.0
remote:
remote: -----> Installing dependencies
remote: Installing node modules (package.json)
remote:
remote: added 160 packages, and audited 161 packages in 4s
remote:
remote: 64 packages are looking for funding
remote: run `npm fund` for details
remote:
remote: found 0 vulnerabilities
remote:
remote: -----> Build
remote:
remote: -----> Caching build
remote: - node_modules
remote:
remote: -----> Pruning devDependencies
remote:
remote: up to date, audited 74 packages in 450ms
remote:
remote: 9 packages are looking for funding
remote: run `npm fund` for details
remote:
remote: found 0 vulnerabilities
remote:
remote: -----> Build succeeded!
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 43.4M
remote: -----> Launching...
remote: Released v3
remote: https://shrouded-anchorage-35377.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/shrouded-anchorage-35377.git
* [new branch] main -> main
アプリのインスタンスが 1 つ以上実行されていることを確認します。
$ heroku ps:scale web=1
アプリ名で生成された URL にあるアプリを開きます。ショートカットで Web サイトを開くことができます。
$ heroku open
ログを表示する
Heroku では、すべてのアプリと Heroku コンポーネントの出力ストリームを、時系列のイベントストリームに集約してログを作成するため、1 か所ですべてのイベントを確認できます。
実行中のアプリに関する情報を表示するには、ログコマンドの 1 つである、heroku logs --tail
を使います。
$ heroku logs --tail
2023-03-02T19:56:09.671017+00:00 heroku[web.1]: Starting process with command `npm start`
2023-03-02T19:56:12.617099+00:00 app[web.1]:
2023-03-02T19:56:12.617126+00:00 app[web.1]: > node-js-getting-started@0.3.0 start
2023-03-02T19:56:12.617127+00:00 app[web.1]: > node index.js
2023-03-02T19:56:12.617127+00:00 app[web.1]:
2023-03-02T19:56:12.738203+00:00 app[web.1]: Listening on 16832
2023-03-02T19:56:13.217147+00:00 heroku[web.1]: State changed from starting to up
ブラウザで再びアプリケーションを表示すると、別のログメッセージが生成されます。
ログのストリーム出力を停止するには、Control+C
を押します。
Procfile を定義する
Procfile は、アプリケーションのルートディレクトリにあるテキストファイルです。このファイルを使って、アプリの起動時に実行するコマンドを明示的に宣言します。
先ほどデプロイしたサンプルアプリの Procfile
は、次のようになっています。
web: npm start
web
という名前は、この 1 つのプロセスタイプが Heroku の HTTP ルーティングスタックにアタッチし、デプロイ後に Web トラフィックを受信することを宣言しているため、重要です。このコマンドでは、package.json
で指定される start
スクリプトを使用します。
Procfile には追加のプロセスタイプを含めることができます。たとえば、キューからアイテムを取り出して処理するバックグラウンドワーカープロセスに対して追加で宣言できます。
アプリをスケールする
現在、アプリは単一の Web dyno で実行されています。dyno とは、Procfile で指定されているコマンドを実行する軽量のコンテナのようなものです。
実行されている dyno の数を確認するには、ps
コマンドを使います。
$ heroku ps
=== web (Eco): npm start (1)
web.1: up 2023/03/02 15:56:13 -0400 (~ 6m ago)
デフォルトでは、アプリは Eco dyno でデプロイされます。トラフィックを何も受信しない場合、Eco dyno はアイドル状態が 30 分続くとスリープします。スリープ解除時、最初のリクエストに数秒の遅延が発生することを想定してください。その後のリクエストは正常に処理されます。Eco dyno はさらに、月ごとに割り当てられるアカウント別の Eco dyno 時間を消費します。割り当て時間が残っている限り、すべての Eco アプリは稼働し続けます。
dyno がスリープしないようにするには、「dyno タイプ」の記事で紹介されている Basic または Professional の dyno タイプにアップグレードできます。たとえば、アプリを Professional dyno に移行すると、Heroku に特定の数の dyno の実行を指示するコマンドを実行し、各 dyno で Web プロセスタイプを実行させて、アプリをスケールすることができます。
Heroku でアプリケーションをスケールするとは、実行中の dyno の数を変更することを意味します。Web dyno の数を 0 にスケールしてみます。
$ heroku ps:scale web=0
ブラウザのタブで更新ボタンを押してアプリにアクセスするか、heroku open
コマンドを使ってブラウザのタブで開きます。リクエストに応答できる Web dyno がなくなったので、エラーメッセージが表示されます。
もう一度スケールしてみましょう。
$ heroku ps:scale web=1
アプリの依存関係を宣言する
Heroku では、ルートディレクトリにある package.json
ファイルによって、アプリを Node.js と認識します。独自のアプリでこのファイルを作成するには、npm init --yes
を実行します。
デプロイしたデモ用アプリには、事前に次のような package.json
が用意されています。
{
"name": "node-js-getting-started",
"version": "0.3.0",
...
"engines": {
"node": "20.x"
},
"dependencies": {
"ejs": "^3.1.5",
"express": "^4.15.2"
},
...
}
package.json
ファイルでは、Heroku でアプリケーションを実行するための Node.js のバージョンと、アプリケーションと一緒にインストールする依存関係を定義します。
このコマンドをローカルディレクトリで実行して依存関係をインストールし、アプリをローカルで実行するためにシステムを準備します。
$ npm install
added 160 packages in 6s
インストール後、npm install
を実行すると package-lock.json
ファイルが生成されます。これを Git にチェックインしてください。後続の依存関係が追加されると、npm でこのファイルが変更されるため、これらの変更も Git に追加するようにしてください。
アプリがデプロイされると、Heroku は package.json
を読み取って適切なノードバージョンをインストールし、package-lock.json
を読み取って依存関係をインストールします。
アプリをローカルで実行する
heroku local
コマンドを使ってアプリケーションをローカルで起動します。このコマンドは、Heroku CLI の一部としてインストールされています。
$ heroku local web --port 5001
[OKAY] Loaded ENV .env File as KEY=VALUE Format
4:09:49 p.m. web.1 | > node-js-getting-started@0.3.0 start
4:09:49 p.m. web.1 | > node index.js
4:09:49 p.m. web.1 | Listening on 5001
Heroku と同じように、heroku local
も Procfile を確認して実行する内容を判断します。
Web ブラウザで http://localhost:5001 を開き、アプリがローカルで実行中であることを確認します。
アプリのローカル実行を停止するには、CLI で Ctrl
+C
を押して終了します。
ローカルの変更をプッシュする
このステップでは、アプリケーションへのローカルでの変更を Heroku に反映させる方法を学びます。例として、アプリケーションを変更して依存関係を追加し、それを使用するコードも追加します。
まず、package.json
で cool-ascii-faces
の依存関係を追加します。 次のコマンドを実行します。
$ npm install cool-ascii-faces
added 11 packages in 2s
起動時にこのモジュールが必要 ( requires
) になるように、index.js
を編集します。これを使用する新しいルート (/cool
) も追加します。最終的なコードは次のようになります。
const cool = require('cool-ascii-faces')
const express = require('express')
const path = require('path')
const PORT = process.env.PORT || 5001
express()
.use(express.static(path.join(__dirname, 'public')))
.set('views', path.join(__dirname, 'views'))
.set('view engine', 'ejs')
.get('/', (req, res) => res.render('pages/index'))
.get('/cool', (req, res) => res.send(cool()))
.listen(PORT, () => console.log(`Listening on ${ PORT }`))
ローカルでテストします。
$ npm install
$ heroku local --port 5001
http://localhost:5001/cool でアプリケーションにアクセスすると、サンプルアプリケーションでは更新のたびに顔文字 ( ⚆ _ ⚆ )
が表示されます。
デプロイします。Heroku へのデプロイは、ほとんどの場合、このパターンで行います。まず、変更したファイルをローカルの Git リポジトリに追加します。
$ git add .
変更内容をリポジトリにコミットします。
$ git commit -m "Add cool face API"
前と同じ方法でデプロイします。
$ git push heroku main
すべてが正常に動作することを確認します。
$ heroku open cool
何も問題がなければ、別の顔文字が表示されます。
アドオンをプロビジョニングする
アドオンは、アプリケーションですぐに使える追加サービスを提供するサードパーティのクラウドサービスです。永続性、ログ記録、モニタリングなど、さまざまなアドオンがあります。
Heroku では、デフォルトで 1,500 行のアプリケーションログが記録されます。ただし、完全なログストリームもサービスとして提供しています。複数のアドオンプロバイダーが、ログの永続化、検索、メールや SMS 通知などの機能を提供するログサービスを用意しています。
このステップでは、このようなログ関連アドオンの 1 つである、Papertrail をプロビジョニングします。
papertrail ログ記録アドオンをプロビジョニングします。
$ heroku addons:create papertrail
Creating papertrail on ⬢ shrouded-anchorage-35377... free
Welcome to Papertrail. Questions and ideas are welcome (technicalsupport@solarwinds.com). Happy logging!
Created papertrail-fluffy-46630 as PAPERTRAIL_API_TOKEN
Use heroku addons:docs papertrail to view documentation
アドオンがデプロイされ、アプリケーション用に設定されました。アプリのアドオンを一覧表示できます。
$ heroku addons
このアドオンが動作していることを確認するため、アプリケーションの Heroku URL に数回アクセスします。アクセスするたびにログメッセージが生成され、papertrail アドオンに送られます。 papertrail のコンソールにアクセスし、ログメッセージを確認します。
$ heroku addons:open papertrail
ブラウザで Papertrail の Web コンソールが開き、最新のログイベントが表示されます。検索したりアラートを設定したりできます。
コンソールを起動する
dyno の仕組みに慣れるため、別の One-off dyno を作成し、この dyno でシェルを開く bash
コマンドを実行してみましょう。シェルが開いたら、そこでコマンドを実行できます。それぞれの dyno には専用の一時的ファイル領域があり、アプリとその依存関係が入力されています。コマンド (この場合は bash
) が完了すると、dyno が削除されます。
$ heroku run bash
Running bash on ⬢ shrouded-anchorage-35377... up, run.1662 (Eco)
~ $ ls
Procfile README.md app.json index.js node_modules package-lock.json package.json public test.js views
~ $ exit
exit
Error connecting to process
が表示された場合は、ファイアウォールを設定してみてください。
シェルを閉じて dyno を終了するには、exit
と入力します。
環境設定を定義する
Heroku では、暗号鍵や外部リソースのアドレスなどのデータを環境設定に保存して、設定を外部に置くことができます。
環境設定は、ランタイムに環境変数としてアプリケーションに提供されます。例として、index.js
を編集し、環境変数 TIMES
の値に応じてあるアクションを繰り返し実行する、/times
という新しいルートを追加します。既存の get()
という呼び出しの下に、次のようにもう 1 つ追加します。
.get('/times', (req, res) => res.send(showTimes()))
ファイルの最後に、showTimes()
という新しい関数の定義を次のように追加します。
function showTimes() {
const times = process.env.TIMES || 5
let result = ''
for (i = 0; i < times; i++) {
result += i + ' '
}
return result
}
heroku local
は、ローカルディレクトリにある .env
ファイルの内容に応じて、環境を自動的に設定します。プロジェクトのトップレベルディレクトリで、.env
ファイルには次の内容が含まれています。
TIMES=2
heroku local --port 5001
でアプリを実行して http://localhost:5001/times を開くと、毎回 2 つの数値が生成されることがわかります。
Heroku で環境設定を設定するには、次のコマンドを実行します。
$ heroku config:set TIMES=2
heroku config
を使って設定した環境設定を表示します。
$ heroku config
=== shrouded-anchorage-35377 Config Vars
PAPERTRAIL_API_TOKEN: w9EnziexBT2mzMDtS4M
TIMES: 2
変更したアプリケーションを Heroku にデプロイし、heroku open times
を実行してアクセスします。
データベースをプロビジョニングする
データベースを使用してこのチュートリアルを完了した場合、使用量のカウントに入ります。コストを抑制するために、完了したらすぐにデータベースを削除してください。低料金プランについて確認してください。資格のある学生の皆様は、Heroku for GitHub Students プログラムを通じてプラットフォームクレジットを申請できます。
add-on marketplace には、Redis や MongoDB、Postgres、MySQL など、多数のデータストアが揃っています。このステップでは、Heroku Postgres Essential-0 データベースをアプリに追加します。
データベースを追加します。
$ heroku addons:create heroku-postgresql:essential-0
Creating heroku-postgresql:essential-0 on ⬢ shrouded-anchorage-35377... ~$0.007/hour (max $5/month)
Database should be available soon
postgresql-asymmetrical-00466 is being created in the background. The app will restart when complete...
Use heroku addons:info postgresql-asymmetrical-00466 to check creation progress
Use heroku addons:docs heroku-postgresql to view documentation
このアクションによりデータベースが作成され、DATABASE_URL
環境変数が設定されます (heroku config
を実行して確認できます)。
npm
を使用して、node-postgres を依存関係に追加します。
$ npm install pg
added 14 packages in 2s
"dependencies": {
"cool-ascii-faces": "^1.3.4",
"ejs": "^3.1.5",
"express": "^4.15.2",
"pg": "^8.11.3"
},
このモジュールを使って DATABASE_URL
環境変数で指定したデータベースに接続できるように、index.js
ファイルを編集します。次のコードを先頭付近に追加します。
const { Pool } = require('pg')
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
})
既存の .get('/', ...)
のすぐ後ろに次のコードを追加して、別のルート /db
を追加します。
.get('/db', async (req, res) => {
try {
const client = await pool.connect();
const result = await client.query('SELECT * FROM test_table');
const results = { 'results': (result) ? result.rows : null};
res.render('pages/db', results );
client.release();
} catch (err) {
console.error(err);
res.send("Error " + err);
}
})
このアクションにより、/db
ルートを使ってアプリにアクセスしたときに、テーブル test_table
のすべての行が返されるようになります。
コードを Heroku にデプロイします。/db
にアクセスすると、データベースにテーブルがないため、エラーが表示されます。ローカル環境に Postgres がインストールされているという前提で、heroku pg:psql
コマンドを使ってリモートデータベースに接続し、テーブルを作成して行を挿入します。
$ heroku pg:psql
--> Connecting to postgresql-asymmetrical-00466
psql (14.7 (Homebrew))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
shrouded-anchorage-35377::DATABASE=> create table test_table (id integer, name text);
CREATE TABLE
shrouded-anchorage-35377::DATABASE=> insert into test_table values (1, 'hello database');
INSERT 0 1
shrouded-anchorage-35377::DATABASE=> \q
この後、heroku open db
でアプリの /db
ルートにアクセスすると、次のように表示されます。
詳細は、「Heroku PostgreSQL」を参照してください。
同様のテクニックを使用して、MongoDB または Redis アドオンをインストールできます。
次のステップ
ここまで、アプリのデプロイ、アプリの設定変更、ログの表示、スケール、アドオンのアタッチを行う方法を説明しました。さらに詳しく知りたい方のために、お勧めするリソースを以下に紹介します。
- アプリケーションの作成、設定、デプロイ、および実行時に必要な技術的な概念の概要については、「Heroku の仕組み」を参照してください。
- Node.js アプリケーションの開発とデプロイの詳細については、Node.js カテゴリを参照してください。
- 既存の Node.js アプリを Heroku にデプロイする方法については、「Heroku で Node.js アプリをデプロイする」を参照してください。