DockerでNode.jsアプリケーションを開発する (4) Herokuにデプロイする
Posted: 2019-11-27
前回まで3回にわたってNode.js/Express.js, MySQLで簡単なアプリケーションを作成して来ましたが、今回は作ったものをいよいよインターネット上に公開する方法を見ていきたいと思います。
ホスティングサービスの検討
Webアプリケーション(もしくはWebサイト)をインターネット上に公開する方法はたくさんあります。
サーバ側で動的な処理をおこなう必要がなくHTML/CSSやJavaScriptなどの静的なアセットを配信するだけであれば、ざっと考えても、
などのサービスが挙げられます。どれもほぼ無料で使える枠があるので気軽に試すことが出来ます。
ただ今回作成しているアプリケーションはNode.jsで動く動的なWebアプリケーションなので、それに対応したホスティングサービスを検討する必要があります。
まず考えられるのは、様々なVPSやAWS EC2、Azure VM, GCP Compute Engineなどのクラウドで動く仮想マシン上にアプリケーションをデプロイする、という方法です。
この方法は自由度が高くて良いのですが、逆に言うとサーバのOSの管理まで含めて全て自分で行わなければならないので、メンテナンスコストが高くつきます。
そこで次に考えられるのは、以下のようなPaaSサービスです。
今回あらためて検索して見たのですが、Node.jsに対応したPaaSサービスでそれなりの実績がありそうなものというと、意外に多くはありませんでした。
最近の流れとしては、「PaaS」ではなく、Firebase Cloud FunctionsやAWS Lambda, Vercelなどを使った「Serverless」な構成の人気が高まって来ているようです。
Node.js/Express.jsで作成したアプリケーションをサーバレスな環境で動かすことも可能ではあるのですが、それはそれでまた考慮しないと行けないことも増えてくるので、今回は十分な実績と人気があるHerokuを使うことにします。
さて、そういうわけでまずはHerokuの公式ドキュメントに目を通しておきましょう。
Getting Started on Heroku with Node.js | Heroku Dev CenterDeploying Node.js Apps on Heroku | Heroku Dev Center
以下、これらのドキュメントの流れにしたがって作業します。
Heroku CLIをインストール
下のページの通りにHeroku CLIをダウンロードしてインストールします。
https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up私の場合はMacなのでbrewでインストールしました。
> brew install heroku/brew/heroku
インストール出来たらCLIでHerokuアカウントにログインします。
> heroku login
Heroku CLIでデプロイ
次にデプロイするのですが、今回のサンプルプロジェクトではアプリケーションのソースコードがプロジェクトのルートフォルダではなくその一階層下のsrcフォルダになっているので、デプロイする前に少しだけ工夫が必要です。
まず、srcフォルダのpackage.jsonファイルとは別に、プロジェクトのルートフォルダに「Herokuにデプロイするため」だけのpackage.jsonファイルを作成します。
Herokuではルートフォルダにpackage.jsonがあるかどうかを見てNode.jsアプリケーションであることを判定しているために必要になります。
"start"でsrcフォルダ内のエントリポイントを指定していることと、"heroku-postbuild"で「--prefix=src」を付けてnpm installを実行するようにしていることに注目してください。
package.json (プロジェクトのルートフォルダ)
{
"name": "docker-nodejs",
"version": "1.0.0",
"scripts": {
"start": "node src/bin/www",
"heroku-postbuild": "npm i --prefix=src"
},
"engines": {
"node": "12.x"
}
}
また、これは無くても多分問題ないと思うのですが、一応プロジェクトのルートフォルダに「Procfile」というファイルを配置しておきます。
Procfile (プロジェクトのルートフォルダ)
web: node src/bin/www
ではHeroku側にアプリケーションを作成しましょう。
> heroku create
上で追加したファイルなどをGitにコミットしておきます。
> git add .
> git commit -m"Add deploy settings for Heroku"
Herokuにデプロイします。
> git push heroku master
これ以降アプリケーションに変更を加えた場合は、Gitにコミット → herokuにプッシュ、という流れで更新していくことになります。
デプロイでエラーが起きなければ、下のコマンドでブラウザを開いてアプリケーションにアクセス出来ます。
> heroku open
今はまだHeroku側でMySQLの設定をしていないので、DB接続でエラーになってしまうと思います。
下のコマンドでアプリケーションから出力されるログをリアルタイムに確認することが出来ます。
> heroku logs -t
赤丸の部分でDB接続エラーになっていることが分かります。
URLの末尾に/usersを付けるか、
> heroku open users
を実行するとダミー文字列のレスポンスが返ってくるはずです。これは現状のソースコードでは /usersのルートハンドラが呼ばれた場合はDBアクセスを行っていないのでエラーにならないからです。
HerokuにMySQLデータベースを追加する
では次のドキュメントに従ってMySQLの設定しましょう。
ClearDB MySQL | Heroku Dev Centerまずアカウントにクレジットカード情報を登録してから、次のコマンドを実行します(クレジットカードは本人確認のために必要で、無料枠の範囲内で使っている限り課金はされないそうです)。
> heroku addons:create cleardb:ignite
MySQLのアドオンが追加出来たら、下のコマンドで接続情報を取得します。
> heroku config | grep CLEARDB_DATABASE_URL
例えば、下のような結果が表示されたとします。
CLEARDB_DATABASE_URL: mysql://b7fcaxxxxxxxx:86efxxxxxxx@us-cdbr-xxxx-east-999.cleardb.net/heroku_b44fa6dxxxxxxxxx?reconnect=true
Node.jsのアプリケーション側でこのDB接続文字列をそのまま使ってDBに接続するようになっていればそれで良いのですが、今回のサンプルアプリケーションでは、
- MYSQL_USER
- MYSQL_PASSWORD
- MYSQL_SERVER
- MYSQL_DATABASE
の4つの環境変数を使っているので、それに合わせて接続文字列を分解してHerokuの「Config Vars」として設定する必要があります。
DB接続文字列は、
mysql://{ユーザー名}:{パスワード}@{サーバー名}/{データベース名}?reconnect=true
となっているようですので、これを下の4つのコマンドに分けて設定します。
> heroku config:set MYSQL_USER='b7fcaxxxxxxxx'
> heroku config:set MYSQL_PASSWORD='86efxxxxxxx'
> heroku config:set MYSQL_SERVER='us-cdbr-xxxx-east-999.cleardb.net'
> heroku config:set MYSQL_DATABASE='heroku_b44fa6dxxxxxxxxx'
この状態で、
> heroku open
を実行すると、今度はDB接続には成功しますが「tasksテーブルが見つからない」というエラーが発生します。まだテーブルを作成していないので当然ですね。
HerokuコンソールからDBマイグレーションを実行する
Heroku側のMySQLにテーブルを作成したり初期データを投入したりするには、Herokuの「Dyno」と呼ばれるコンテナのシェルに接続して、DBマイグレーションを実行する必要があります。
> heroku run bash
を実行するとDynoのシェルに接続出来ます。
ただ、手元で試したときには下のエラーが出て接続出来ないことが何回かありました。
このエラーが出る場合は、下のWebコンソールを使う方法を試してみてください。
Herokuの管理画面の右上にある「More」というメニューを開いて、「Run console」をクリックします。
このコンソール上で、
> cd src
> npx sequelize-cli db:migrate
> npx sequelize-cli db:seed:all
を実行します。
これでデータベースへのテーブル作成と初期データ投入が完了します。
> heroku open
でアプリケーションが開いてタスク一覧画面が表示されれば、ついにインターネットへの公開が完了です!
ソースコード
ここまでの全ソースコードは下記で確認出来ます。
https://github.com/ishidait/docker-nodejs/tree/blog-4