Node.js / Express アプリのデプロイ(PM2 + Nginx)
『Node.js / Express アプリのデプロイ』では、プロセスマネージャー PM2 による自動再起動・ログ管理と、Nginx をリバースプロキシとして前段に置く構成を解説します。PM2 は Node.js アプリをデーモンとして動かし、クラッシュ時の自動再起動・起動時の自動実行設定・リアルタイムログ監視を提供します。Nginx と組み合わせることで、HTTPS 終端・静的ファイル配信・複数アプリのバーチャルホスト管理を効率よく行えます。
構文
# -----------------------------------------------
# PM2 のインストール(グローバル)
# -----------------------------------------------
# npm i -g pm2
# → PM2 をグローバルにインストールします
# 例: sudo npm install -g pm2
# -----------------------------------------------
# アプリの起動・停止・再起動
# -----------------------------------------------
# pm2 start {スクリプト} --name {名前}
# → Node.js アプリをデーモンとして起動します
# → --name でプロセス名を付けると管理しやすくなります
# 例: pm2 start app.js --name akane-express
# pm2 stop {名前|id|all}
# → プロセスを停止します(プロセスリストからは削除されません)
# 例: pm2 stop akane-express
# 例: pm2 stop all
# pm2 restart {名前|id|all}
# → プロセスを再起動します。コード更新後に使用します
# 例: pm2 restart akane-express
# pm2 reload {名前|id|all}
# → ゼロダウンタイムでプロセスを再起動します
# → クラスター(cluster)モードで動作している場合に有効です
# 例: pm2 reload akane-express
# pm2 delete {名前|id|all}
# → プロセスを停止してリストから完全に削除します
# 例: pm2 delete akane-express
# -----------------------------------------------
# プロセスの確認・ログ・モニター
# -----------------------------------------------
# pm2 list
# → 管理中のプロセス一覧をテーブル形式で表示します
# pm2 logs {名前|id}
# → リアルタイムでログを表示します(stdout + stderr)
# → 引数なしで全プロセスのログを表示します
# 例: pm2 logs akane-express
# 例: pm2 logs akane-express --lines 100
# pm2 monit
# → CPU・メモリ使用率をリアルタイムで表示するダッシュボードを開きます
# -----------------------------------------------
# OS 起動時の自動実行設定
# -----------------------------------------------
# pm2 startup
# → OS 起動時に PM2 が自動起動するよう systemd ユニットを生成します
# → 出力されたコマンドをコピーして実行する必要があります
# pm2 save
# → 現在のプロセスリストをダンプファイルに保存します
# → pm2 startup と組み合わせてサーバー再起動後に自動復元されます
# -----------------------------------------------
# エコシステムファイル(複数アプリの一括管理)
# -----------------------------------------------
# pm2 ecosystem
# → ecosystem.config.js のひな形を生成します
# pm2 start ecosystem.config.js
# → エコシステムファイルに定義したアプリをまとめて起動します
構文一覧
| コマンド | 説明 |
|---|---|
pm2 start {スクリプト} --name {名前} | Node.js アプリをデーモンとして起動します。--name でプロセス名を付けると stop / restart で名前指定できます。 |
pm2 stop {名前|id|all} | プロセスを停止します。all を指定すると管理中の全プロセスを停止します。プロセスリストからは削除されません。 |
pm2 restart {名前|id|all} | プロセスを再起動します。コードの更新後に実行します。 |
pm2 reload {名前|id|all} | クラスターモードでゼロダウンタイム再起動を行います。サービスを止めずにコードを反映できます。 |
pm2 delete {名前|id|all} | プロセスを停止してリストから完全に削除します。不要になったアプリを整理するときに使用します。 |
pm2 list | 管理中のプロセス一覧を表示します。状態・CPU・メモリ使用量・再起動回数などを確認できます。 |
pm2 logs {名前|id} | リアルタイムでログを表示します。--lines {N} で過去 N 行を遡れます。 |
pm2 monit | CPU・メモリ使用率をリアルタイム表示するターミナルダッシュボードを起動します。 |
pm2 startup | OS 起動時に PM2 が自動起動するための systemd ユニットファイルを生成します。出力コマンドをそのまま実行します。 |
pm2 save | 現在のプロセスリストをダンプファイルに保存します。pm2 startup と組み合わせてサーバー再起動後に自動復元されます。 |
pm2 ecosystem | ecosystem.config.js のひな形を生成します。複数アプリや環境変数を一元管理できます。 |
pm2 start ecosystem.config.js | エコシステムファイルに定義したアプリをまとめて起動します。本番・開発環境の切り替えも容易です。 |
使用例
PM2 でアプリを起動・自動起動設定
# ----------------------------------------------- # Express アプリを PM2 で起動し、OS 再起動後も # 自動的に立ち上がるよう設定します # ----------------------------------------------- # アプリのディレクトリに移動して依存パッケージをインストールします cd /var/www/akane-express npm install --production # PM2 でアプリを起動します # --name で付けた名前が pm2 list や pm2 logs で使えます pm2 start app.js --name akane-express # ----------------------------------------------- # OS 起動時の自動実行を設定します # ----------------------------------------------- # pm2 startup が systemd ユニットを作成するコマンドを出力します # 出力されたコマンドをそのままコピーして実行してください pm2 startup # 現在動作中のプロセスリストを保存します # これにより OS 再起動後も akane-express が自動起動します pm2 save
実行するコマンドは次の通りです。
$ pm2 list ┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ ├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ │ 0 │ akane-express │ default │ 1.4.2 │ fork │ 12483 │ 3D │ 0 │ online │ 0% │ 58.2mb │ akane │ disabled │ │ 1 │ ginoza-api │ default │ 2.1.0 │ cluster │ 12501 │ 3D │ 0 │ online │ 0% │ 61.7mb │ akane │ disabled │ └────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
/etc/nginx/sites-available/akane-express.conf
# -----------------------------------------------
# Nginx リバースプロキシ設定
# Node.js / Express アプリ(ポート 3000)への転送
# -----------------------------------------------
server {
listen 80;
server_name akane.psycho-pass.example.com;
# HTTP アクセスはすべて HTTPS にリダイレクトします
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name akane.psycho-pass.example.com;
# SSL 証明書(Let's Encrypt で取得したファイルを指定します)
ssl_certificate /etc/letsencrypt/live/akane.psycho-pass.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/akane.psycho-pass.example.com/privkey.pem;
# -----------------------------------------------
# 静的ファイルは Nginx が直接配信します
# Node.js へのプロキシを経由しないため高速です
# -----------------------------------------------
location /static/ {
alias /var/www/akane-express/public/;
expires 30d;
access_log off;
}
# -----------------------------------------------
# 上記以外のリクエストをローカルの Express へ転送します
# -----------------------------------------------
location / {
proxy_pass http://127.0.0.1:3000;
# クライアントの実 IP・プロトコルをアプリに伝えます
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket を使う場合は以下の設定も追加します
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
}
}
実行するコマンドは次の通りです。
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful $ sudo systemctl reload nginx $ pm2 logs akane-express --lines 5 [TAILING] Tailing last 5 lines for [akane-express] process (change the value with --lines option) /root/.pm2/logs/akane-express-out.log last 5 lines: 0|akane-ex | 常守朱のダッシュボードが起動しました (port: 3000) 0|akane-ex | GET /api/inspectors 200 12ms 0|akane-ex | GET /api/dominators 200 8ms 0|akane-ex | POST /api/crime-coefficient 201 34ms 0|akane-ex | GET /static/img/psycho-pass-logo.png 304 2ms
ecosystem.config.js で複数アプリを一括管理する
# ----------------------------------------------- # ecosystem.config.js のひな形を生成します # ----------------------------------------------- pm2 ecosystem
同じ処理を次のようにも書けます。
// ecosystem.config.js
// 常守朱の Express アプリと宜野座のAPIサーバーをまとめて管理します
module.exports = {
apps: [
{
// 常守朱が担当するメインの Express アプリです
name : 'akane-express',
script : './app.js',
instances: 1,
exec_mode: 'fork',
env: {
NODE_ENV: 'development',
PORT : 3000,
},
env_production: {
NODE_ENV: 'production',
PORT : 3000,
},
// 1GB を超えたら PM2 が自動再起動します
max_memory_restart: '1G',
// ログファイルの保存先を指定します
out_file : '/var/log/akane-express/out.log',
error_file: '/var/log/akane-express/err.log',
},
{
// 宜野座が担当する内部 API サーバーです
name : 'ginoza-api',
script : './api/server.js',
instances: 2,
exec_mode: 'cluster',
env_production: {
NODE_ENV: 'production',
PORT : 3001,
},
},
],
};
同じ処理を次のようにも書けます。
# 本番環境として起動します(env_production が適用されます) pm2 start ecosystem.config.js --env production # プロセスリストを保存して OS 再起動後も自動復元されるようにします pm2 save
概要
『Node.js / Express アプリのデプロイ』では PM2 と Nginx の組み合わせが広く採用されています。PM2 は Node.js 専用のプロセスマネージャーで、アプリのクラッシュ時の自動再起動・クラスターモードによるマルチコア活用・『pm2 startup』と『pm2 save』を使った OS 再起動後の自動実行設定を提供します。Nginx はリバースプロキシとして前段に置き、SSL 終端・静的ファイルの高速配信・ロードバランシングを担当します。Node.js アプリはポート 3000 などでローカルリッスンし、外部からのアクセスは Nginx がポート 443 で受けて転送するため、Node.js プロセスを root 権限で動かす必要がありません。Nginx のリバースプロキシ詳細設定については Nginx リバースプロキシ のページを、PM2 が生成する systemd ユニットの仕組みについては systemd ユニット のページを参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。