DELOGs
[自サーバでNext.jsアプリを動かす#2]PM2を利用して、快適にNext.jsアプリを動かす

自サーバでNext.jsアプリを動かす#2
PM2を利用して、快適にNext.jsアプリを動かす

Next.jsで作成したWebサイト・アプリを自サーバで運用するために「PM2」というミドルウェアを利用して、快適に運用して方法のまとめ

初回公開日

最終更新日

前回「自サーバでNext.jsアプリを動かす#1 Node.jsインストール+Nginx設定+デプロイ」で行った作業では、npm startでnode.jsを使ってWebアプリを起動しました。
前回の確認はこちら...
しかし、通常、Node.jsアプリはnpm startなどで起動すると、そのターミナルが閉じられたら終了してしまうという特性がある。 これでは、サーバ再起動やSSH切断などに弱く、本番環境での運用はできません。 そこで登場するのが、プロセスマネージャーと呼ばれる広義のミドルウェアです。
私の環境で採用しているプロセスマネージャーは「PM2」です。

1.「PM2」とは?

PM2(Process Manager 2) は、Node.jsアプリケーションを本番環境で安定して常駐・管理するためのプロセスマネージャです。
PM2の主な機能は下記のとおりです。
  • アプリをバックグラウンドで常駐実行
  • サーバ再起動後にも自動復元(systemd連携)
  • ログの一元管理
  • 複数アプリのプロセスをまとめて管理
こうした運用に必要な機能をぜんぶカバーしてくれる便利ツールです。
○npm start と PM2 の違い
観点npm startPM2
実行方法nodeで直接起動バックグラウンドで常駐起動
ターミナル閉じたら?❌ アプリも終了✅ アプリは生きたまま維持
再起動後の自動復元❌ できない✅ pm2 startup + pm2 save で対応可
ログ管理❌ 手動でリダイレクトする必要あり✅ pm2 logs で即確認
複数プロセス管理❌ 別ターミナルで個別に起動✅ 一括管理・再起動・再保存が可能
○他に同様のプロセスマネージャは?
ミドルウェア名特徴
forever初期に使われてたプロセスマネージャ。シンプルだが、機能が少ない
nodemon開発用。コード変更を検知して自動再起動するツール。本番には不向き
systemdOSレベルのプロセス管理。柔軟だが設定が複雑。PM2と併用されることも多い
  • PM2は「開発でも本番でも使える」「機能が豊富」「導入が簡単」な三拍子そろったツールです
↓プロセスマネージャのイメージです:
text
1[ クライアント ] 234+-------------+   +--------------------+ +------------------------+ 5| Nginx |───▶| PM2 |─────▶| Next.js アプリ | 6| (リバースプロキシ) | | (プロセスマネージャ) | | (バックエンド処理) | 7+-------------+   +--------------------+ +------------------------+
この図のように、Nginxはインターネットからのリクエストを受け取り、PM2によって常駐管理されているNext.jsアプリにリクエストを中継します。
PM2は単なる起動ツールではなく、プロセスの監視・復旧・ログ管理・自動起動まで担う「アプリ運用の屋台骨」となる存在です。

2.【サーバ側作業】PM2のインストールと実行

PM2のインストール

bash
1sudo apt update 2sudo npm install -g pm2

PM2の実行

bash
1cd /var/www/example.com/html/ 2pm2 start npm --name "new-app" -- start
  • --name "new-app"の自分が覚えやすい名前でOK
とりあえず、これでブラウザでNext.jsのデフォルトページは表示できます。 ぜひ、確認してみてください。
pm2 start npm --name "new-app" -- startしただけですと、サーバを再起動した時に再度コマンドを実行する必要があります。 サーバの再起動時も自動的にpm2で起動させる方法は下記のようになります。

PM2をサーバ起動時に自動起動させる手順

pm2 startup を実行:
bash
1pm2 startup
上記のコマンドを実行すると、下記のようなメッセージが表示されます。
bash
1[PM2] Init system found: systemd 2[PM2] To setup the startup script, copy/paste the following command: 3sudo env PATH=$PATH:/home/***/.nvm/versions/node/v22.14.0/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u *** --hp /home/***
sudo env ・・・の部分をコピー&ペーストしてコマンド実行します。
bash
1sudo env PATH=$PATH:/home/***/.nvm/versions/node/v22.14.0/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u *** --hp /home/***
以上は、そのサーバ、そのユーザー、そのOSに1回だけ実行すればOKです。
現在のプロセスリストを保存(必須):
bash
1pm2 save
↑これをしないと「登録したけど何を起動するか」が空っぽで、再起動しても何も復元されないので、注意が必要です。
  • pm2 saveで現在稼働中のプロジェクトを保存するものです。
例えば、新たなプロジェクトを稼働させた時は
bash
1cd /var/www/hogehoge.com/html/ 2pm2 start npm --name "new-app2" -- start 3pm2 save
このように、pm2 startpm2 saveを実行するだけでサーバ再起動時に自動でプロジェクトを稼働してくれます。

pm2で稼働中のプロジェクトの確認

bash
1pm2 list
bash
1┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ 2id │ name │ mode │ ↺ │ status │ cpu │ memory │ 3├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ 40 │ new-app │ fork │ 0 │ online │ 0% │ 67.9mb │ 5└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
  • name欄はpm2 startコマンドで指定したnameになります。

pm2で稼働中のプロジェクトを停止

bash
1pm2 delete new-app 2pm2 save
  • pm2 listで表示されるnameを指定して削除できます。idの数値でpm2 delete 0としてもOKです。
  • pm2 saveで自動実行の定義にも反映
全てのプロジェクトの停止する場合:
bash
1pm2 delete all 2pm2 save

稼働中のPM2プロジェクトを再起動

何か設定変更したり、再アップロードした場合はPM2もリスタートする必要があります。
bash
1pm2 restart new-app 2pm2 save
  • restartコマンドも名前指定だけでなくid指定でpm2 restart 0とすることもできます。
全てのプロジェクトの再起動する場合:
bash
1pm2 restart all 2pm2 save

2. PM2を利用したNext.js本番運用のまとめ:デプロイ後の定型手順

本番へファイルをアップロード後
bash
1# 1. 対象のルートディレクトリへ移動 2cd /var/www/example.com/html 3 4# 2. 依存関係をロックファイルに基づいてインストール 5npm ci 6 7# 3. [Prismaを利用中の場合]Prisma Client の再生成(DBスキーマが変わってなくても基本実行) 8npx prisma generate 9 10# 4. PM2でNext.jsを起動 11# [稼働中のプロジェクトの場合]-PM2を再起動 12pm2 restart new-app 13 14# [新規プロジェクトの場合]-PM2で新規スタート 15pm2 start npm --name "new-app2" -- start 16 17# 5. 現在のプロセス構成を保存(再起動後に自動復元させるため) 18pm2 save

3. PM2をもっと便利に使う! ecosystem.config.js の活用

ここまで紹介してきたPM2の操作はすべて、コマンドラインで1つずつ手動で実行していました。 実際の運用では、複数のアプリや環境変数の管理、ログパスの指定なども行いたくなる場面が多くなってきます。
そこで活用したいのが、PM2の構成ファイル ecosystem.config.js です。
このファイルを使えば、
  • 環境変数の設定(.envの代わり)
  • スクリプトの指定(npm run startのような)
  • アプリごとのログや再起動設定
  • 複数アプリの管理
などが、すべて1つのファイルで自動化できます。

運用ポリシー

色々な利用の仕方がありますが、私の場合は下記のポリシーでPM2を運用することにしています。
項目方針
ecosystem.config.jsの配置各サイトルートには置かず、ホームディレクトリに配置
サイトごとに管理サイトごとにファイルを分割(例:ecosystem-delogs.config.js)
.envファイル使用しない(env オブジェクト内で環境変数を定義)
公開ディレクトリのセキュリティ重要設定ファイルはすべて非公開領域に集約

ディレクトリ構成(例)

text
1/home/user/ 2├── pm2/ 3│ ├── ecosystem-example.config.js(←ここにpm2設定ファイル) 4│ └── ecosystem-hogehoge.config.js(←サイト毎に分けて管理) 5/var/www/ 6├── example.com/ 7│ └── html/(←ここに公開ファイル)
  • 設定ファイルは非公開領域のサーバの各ユーザのホームディレクトリに配置

ecosystem-example.config.js の設定

bash
1cd ~ 2mkdir pm2 3vi pm2/ecosystem-example.config.js
設定例:
bash : ecosystem-example.config.js
1// /home/user/pm2/ecosystem-example.config.js 2 3module.exports = { 4 apps: [ 5 { 6 name: 'example-app', 7 cwd: '/var/www/example.com/html/', 8 script: 'npm', 9 args: 'start', 10 instances: 1, 11 autorestart: true, 12 watch: false, 13 max_memory_restart: '1G', 14 env: { 15 NODE_ENV: 'production', 16 NEXT_PUBLIC_SITE_NAME: 'example', 17 DATABASE_URL: 'postgresql://dbuser:yourpassword@xxx.xxxx.xxx.xxx:5432/dbname?schema=public' 18 } 19 } 20 ] 21}
○各設定項目の説明
項目名説明
namePM2で表示されるアプリ名(pm2 listに出る)
cwdカレントワーキングディレクトリ(ルートディレクトリ)
script起動するスクリプト(Next.jsならnpm)
argsnpmに渡す引数(start → npm start)
instancesクラスタモード用(Next.jsでは基本1でOK)
autorestartアプリが落ちたら自動で再起動する
watchファイルの変更時に再起動させるか。falseの場合、手動でpm2 restartしたときだけ再起動(本番環境はこれ)
max_memory_restartメモリが1GB超えたら再起動
env環境変数(.envファイル代わりにここで指定
  • ecosystem.config.js は Node.jsの module.exports 構文を使った JavaScriptファイルになります。コメントアウトする際は通常のJavaScriptと同じです。///* */を利用します。
  • env:{}にNext.jsの.envの内容を記述しますが、NODE_ENV: 'production',のような:で区切る記述の仕方になります。Next.js側ではNODE_ENV='production'=で指定いると思うので注意してください。
  • max_memory_restartは難しいところです。あまり頻繁に再起動しても困るので、サーバスペックと相談して決めます。pm2 listpm2 monitで利用メモリがチェックできます。 MBでしてする場合は512Mなどと指定します。

起動&保存手順(サーバ再起動対応)

bash
1pm2 start ~/pm2/ecosystem-example.config.js 2pm2 save
bash
1pm2 list
  • example-appが表示されればOK
リスタート時:
bash
1pm2 restart ~/pm2/ecosystem-example.config.js 2pm2 save
  • 設定ファイルを更新した時だけなく、公開ファイルを更新した際も必ず、~/pm2/ecosystem-example.config.jsをつけて実行してください。
  • 私は~/pm2/ecosystem-example.config.jsをつけずにリスタートした時に環境設定ファイルを読み込んでくれない現象を経験しました。
これで、効率的な運用もできるようになったと思います。改めて、ecosystem.config.jsを利用した場合のNext.js本番運用のまとめを記します。

4. PM2のecosystem.config.jsを利用したNext.js本番運用のまとめ:デプロイ後の定型手順

本番へファイルをアップロード後
bash
1# 1. 対象のルートディレクトリへ移動 2cd /var/www/example.com/html 3 4# 2. 依存関係をロックファイルに基づいてインストール 5npm ci 6 7# 3. [Prismaを利用中の場合]Prisma Client の再生成(DBスキーマが変わってなくても基本実行) 8npx prisma generate 9 10# 4. PM2でNext.jsを起動 11# [稼働中のプロジェクトの場合]-PM2を再起動 12pm2 restart ~/pm2/ecosystem-example.config.js 13 14# [新規プロジェクトの場合]-PM2で新規スタート 15pm2 start ~/pm2/ecosystem-example.config.js 16 17# 5. 現在のプロセス構成を保存(再起動後に自動復元させるため) 18pm2 save
以上となります。これで一通り、Next.jsのwebアプリを自サーバで動かすことができるようになったと思います。
次回は、Nginxの設定に戻り、キャッシュ管理についての設定を行います。
続きはこちら...
前回の確認はこちら...
この記事の執筆・編集担当
DE

松本 孝太郎

DELOGs編集部/中年新米プログラマー

ここ数年はReact&MUIのフロントエンドエンジニアって感じでしたが、Next.jsを学んで少しずつできることが広がりつつあります。その実践記録をできるだけ共有していければと思っています。