
PM2 でNext.jsを動かしている VPS では、何も設定しなければプロセスが使うメモリに上限がありません。 メモリが増え続けてもPM2は何もしないため、最終的にサーバー全体が不安定になる可能性があります。
この記事では、なぜメモリの制御が必要なのか、どのような設定を入れたのか、そしてその設定を ecosystem.config.js というファイルで管理するようにした理由を書きます。
メインブログの第23回でGitとGitHubによるバックアップ環境を構築した話を書きました。 今回の話はその延長にもつながっています。
第23回:VPSのNext.jsブログをGitとGitHubでバックアップ・バージョン管理する方法
なぜメモリの制御が必要なのか
このブログは2GB の VPS 上で動いています。 OS や Nginx などのシステム全体でメモリを使うため、Next.js が使えるメモリはその一部です。
Node.js(Next.js の実行環境)はメモリリークと呼ばれる現象を起こすことがあります。 メモリリークとは、「使い終わったメモリが解放されずに蓄積し続ける」状態のことです。 コードに問題がなくても、長期稼働しているうちにじわじわとメモリ使用量が増えていくケースがあります。
放置するとどうなるか。 メモリが足りなくなったOSは、プロセスを強制終了し始めます。 ブログが突然表示されなくなる原因のひとつがこれです。
対策として有効なのが、PM2 の max_memory_restart という設定です。
指定したメモリ使用量を超えたときに PM2 が自動的にプロセスを再起動してくれます。
再起動によってメモリがリセットされるため、蓄積を防げます。
どのような設定を入れたか
今回入れた設定は max_memory_restart だけではありません。
あわせて再起動の制御に関する設定もまとめて整理しました。
max_memory_restart: "400M"
メモリ使用量が 400MB を超えたときに自動再起動します。 2GB の VPS で Next.js が通常 70〜80MB 程度のメモリを使うことを考えると、400MB という値は「明らかに何かがおかしい」状態を検知するための余裕を持った上限です。
autorestart: true
クラッシュしたときに自動で再起動します。 デフォルトで有効ですが、明示的に書いておくことで設定の意図が明確になります。
watch: false
ファイルの変更を検知して自動再起動する機能を無効にします。 開発中は便利ですが、本番環境ではデプロイのたびにファイルが変わるため、不要な再起動が頻発してしまいます。必ず無効にします。
min_uptime: "10s"
起動してから10秒以上稼働した場合に「正常に起動した」とみなします。 10秒未満でクラッシュした場合は「異常な終了」としてカウントします。
max_restarts: 10
異常な終了が連続10回起きたら、PM2 は再起動を諦めます。 何らかの根本的な問題がある場合に、無限に再起動し続けてサーバーに負荷をかけ続けることを防ぎます。
exec_mode: "fork"
PM2 にはシングルプロセスで動く fork モードと、複数プロセスで並列処理する cluster モードがあります。
cluster モードはプロセス数分のメモリを消費するため、2GB の VPS では逆にメモリを圧迫します。
個人ブログ規模では fork で十分です。
NODE_ENV: "production"
Next.js を本番モードで動作させます。 開発用のデバッグ情報を出力しなくなり、パフォーマンスが上がります。
これをコマンドで毎回指定するのは現実的ではない
上記の設定を pm2 start のコマンドラインで毎回指定すると、このような長いコマンドになります。
bashpm2 start npm --name "example-blog" --max-memory-restart 400M -- start
これだけでも十分長いですが、exec_mode や min_uptime などの設定を加えようとするとさらに複雑になります。
また、コマンドを直接打つ方式では「今どんな設定で動いているか」をコードとして残すことができません。
ecosystem.config.js で管理するようにした
PM2 には設定をファイルで管理する仕組みがあります。
ecosystem.config.js というファイルにすべての設定を書いておくことで、起動コマンドを短くできます。
~/example-blog/ に以下のファイルを作成しました。
javascriptmodule.exports = { apps: [ { name: "example-blog", script: "npm", args: "start", cwd: "/home/username/example-blog", exec_mode: "fork", instances: 1, max_memory_restart: "400M", autorestart: true, watch: false, min_uptime: "10s", max_restarts: 10, env: { NODE_ENV: "production", }, }, ], };
このファイルがあれば、起動コマンドは以下の1行になります。
bashpm2 start ~/example-blog/ecosystem.config.js
~/example-blog/ に置くことで Git でバックアップされる
ecosystem.config.js を ~/example-blog/ の中に置いたことには、もうひとつ重要な意味があります。
このブログのソースコードは GitHub のプライベートリポジトリでバックアップしています。
~/example-blog/ 以下のファイルが対象のため、ecosystem.config.js もそのままバックアップ対象に含まれます。
万一 VPS が壊れて再構築が必要になったとき、GitHub からソースコードを git clone するだけで PM2 の設定も一緒に復元できます。
bashcd ~ git clone git@github.com:username/example-blog.git pm2 start ~/example-blog/ecosystem.config.js pm2 save
「設定をコードとして管理する」という考え方は Infrastructure as Code と呼ばれます。 難しい概念ではなく、「設定をファイルに書いてバージョン管理する」というシンプルな発想です。
ecosystem.config.js を使う場合のコマンド
ecosystem.config.js を導入した後は、PM2 の操作コマンドが以下のように変わります。
初回起動・再登録時(VPS 再構築後など)
bashpm2 start ~/example-blog/ecosystem.config.js pm2 save
通常のデプロイ時(deploy.sh から実行)
bashpm2 restart ecosystem.config.js --update-env
--update-env は env セクションで定義した環境変数の変更を反映するためのオプションです。
このオプションをつけておくことで、設定ファイルの env を変更したときに確実に反映されます。
プロセスの状態確認
bashpm2 list pm2 show example-blog
停止・削除
bashpm2 stop example-blog pm2 delete example-blog
max_memory_restart の確認方法について
pm2 show example-blog を実行しても、max_memory_restart の項目は表示されません。
これは PM2 の表示上の仕様です。
実際に設定が機能しているかどうかは、以下のコマンドで確認します。
bashcat ~/.pm2/dump.pm2 | grep max_memory
"max_memory_restart": 419430400 のように表示されれば、400MB の設定が正しく保存されています(419430400 バイト = 400MB)。





