この記事の内容
- Nodejsアプリをどうデプロイしようか
- pm2というマネージャ
- サービス化
どうサービスに乗せるのか
Nodejsを基盤とするWebアプリケーションはその守備範囲の広さから、アプリそのものが直接リクエストを受け付けることができます。
Javaや.NETではアプリケーションサーバ(GlassfishやIIS)がクライアントからのレスポンスを受け付けて、そこからレスポンスをアプリケーションに投げるわけですが、一方でNodejs Webアプリケーションはクライアントからのリクエストを直接受け取り、それを処理します。
Javaや.NETにおいてはアプリケーションサーバという階層があり、サービスとしての起動などはこの階層でよしなにやってくれます。
しかし、Nodejsではどうでしょう?
HerokuやOpenShiftなどのクラウドにデプロイしているから意識していない?
シェルスクリプトで cd ${applicationRoot}; node ./bin/app.js
を実行させる? スマートじゃないですね。
サービス化するための選択肢
自前のサーバ上でNodejsアプリケーションをサービス化する試みはいくつかあって、
- winser
- windows上でサービス化するためのライブラリ
- forever
- linux/macOS上でのサービス化するためのデーモンマネージャ
- pm2
- Advanced, production process manager for Node.js
と言ったところがすぐ見つかるところ。
LinuxならPM2
Windows上でサービス化しようとするとwinserが唯一の選択肢、と言ったところですが、Linux/UNIXではforeverとpm2があります。
先発プロダクトがforeverで、後発がpm2です。
後発だけあって、pm2はかなり機能が充実しています。
- 自前ロードバランサ搭載で、クラスタ化可能
- pm2自体がロードバランサとして動作することで、アプリケーションのクラスタリングを簡単に行うことができます。
つまり、アプリケーション側でクラスタリングを実装する必要がないということ!
- pm2自体がロードバランサとして動作することで、アプリケーションのクラスタリングを簡単に行うことができます。
- 分散したログの集約閲覧
- アプリのクラスタリングをするとノード単位にログが出力され、何が時系列に挙動を追跡するのが難しくなります。
しかしpm2ではそれらログを統合し、一挙に確認できるようにしています。
- アプリのクラスタリングをするとノード単位にログが出力され、何が時系列に挙動を追跡するのが難しくなります。
- 設定ファイルで簡単起動
- デプロイするサービスを設定ファイル(js/json/yml)に記述し、起動時に読み込めばもろもろの設定込みで起動ができます。
- 環境スイッチ付き
- サービス設定ファイルに環境別の環境変数を設定することで、起動時にどの環境を使用するかスイッチすることができます。
- デプロイ機能つき
- Gitのリポジトリを利用したリモートサーバへのデプロイ機能があります。
いろいろと機能があって全てを網羅するのは大変ですが、pm2を使用してNodejsアプリのサービス化を行ってみたいと思います。
pm2でサービス化
ここではトランスパイルしたファイルを使用し、Herokuなどではなく自前のサーバでサービス実行するまでの手順を説明します。
このセクションでは、以下のサーバ・所有者で実行することを目指します。
前提
- バージョン
mw / lib | version |
---|---|
node | v9.0.0 |
pm2 | 2.7.2 |
- サービス化環境
key | value |
---|---|
サーバ | sampleServ |
デプロイ先 | /opt/NodeApps/sample |
実行ユーザ | sample:sample。 sudoコマンド実行可能 |
デプロイ先/opt/NodeApps/sampleにはすでにアプリ資産がリリースされており、 npm install
も完了している状況です。
本当はpm2のデプロイ機能も使いたかったけれど、サービス化するのが一杯一杯だったので。
サービス化手順
まずはpm2がなければ意味がないのでインストールします。
# npm install -g pm2
今度は実行ユーザにスイッチして、Nodejsのアプリケーションルートに移動します。pm2コマンドを実行するユーザがアプリの実行ユーザとなるので、
また、アプリケーション以下全てのファイルが実行ユーザの所有者である必要があります。
ではpm2で起動! となりますがちょっと待って。
設定ファイルを作りましょう。
{
"apps": [
{
"name" : "sample",
"script" : "./bin/application.js",
"instances" : 0,
"watch" : true,
"exec_mode" : "cluster",
"source_map_support": true,
"env": {
"PORT": 8000,
"NODE_ENV": "development"
},
"env_production" : {
"NODE_ENV": "production"
}
}
]
}
pm2に吸い込ませる設定ファイルはappsプロパティの配列として定義します。これは複数のNodejsアプリを同一設定で呼び出すことができることを示しています。
それぞれのパラメータはpm2のリファレンスを見てもらうとして、特記すべきは exec_mode
と instances
ですね。
exec_mode: "cluster"
を設定すればクラスタリングの設定となり、 instances : 0
とすればサーバが持つCPUコアの数だけノードを展開します(1以上の値を設定すれば使用するコア数=ノード数を設定できる)。
設定ファイルが書き上がってようやく起動です。
# cd /opt/NodeApps/sample
# pm2 start ./pm2-service.json --env production
pm2コマンドをsudoで実行すればrootが、sudoなしで実行すればカレントユーザーがサービスの実行ユーザとなります。
そして、 --env
オプションが環境スイッチです。
pm2-service.json
にある env.env_production
が環境変数として設定されて実行します。
env.env
はデフォルト設定、 env_*
とあるものは --env
に*を指定します。
e.g.) --env staging
とすれば env.env_staging
の設定が読み込まれます。
起動したしコレでOK、と思ってはいけません。pm2でのサービス起動の永続化には、 「現在の状況を記憶」 させる必要があります。
pm2では
- 最終的にあるべきサービス状態を構築
- 状態を記録し、永続化する
という流れでサービス化します。
# sudo pm2 startup [platform] -u sample
# pm2 save
[platform]は実行サーバのinitシステムによって変化します。
- systemd
- upstart
- launchd
- rcd
気をつけなければならないことは、実行ユーザをroot以外にする場合 -u
オプションを忘れてはならないということです。
コレを忘れてしまうと、たとえ想定する実行ユーザで操作をしていたとしても、サーバ再起動をするとrootでアプリが動作します。