Node.jsで「Error: listen EADDRINUSE: address already in use」エラー

Node.js を使って開発をしていると、サーバーを起動し直したときに 「Error: listen EADDRINUSE: address already in use」 というエラーに遭遇することがあります。これは Node.js 初心者から中級者まで多くの人が一度は経験する代表的なトラブルです。エラーメッセージを直訳すると「アドレスはすでに使用中」という意味で、つまり 指定したポート番号が他のプロセスによってすでに占有されている 状態を指しています。

本記事では、このエラーが発生する原因とその解決方法について整理します。Node.js に限らず、Web 開発全般で役立つ知識なので、ぜひ参考にしてください。

1. EADDRINUSE エラーとは何か

EADDRINUSE は OS レベルで割り当てる通信ポートが競合しているときに発生するエラーコードです。Node.js の場合、http.createServer()app.listen() などでサーバーを起動するときに、指定されたポート番号がすでに他のプロセスに占有されているとこのエラーが返されます。

例として、ポート 3000 番でサーバーを起動したいときに、すでに別の Node.js プロセスやアプリケーションが同じポートを使用中であると、以下のようなエラーが出力されます。

Error: listen EADDRINUSE: address already in use :::3000

ここで :::3000 は IPv6 形式でポート 3000 を示しています。つまり 「ポート 3000 はすでに使われているため、このサーバーは起動できない」 という意味です。

図解イメージ:

[Node.js サーバーA] --- ポート3000 --- OK
[Node.js サーバーB] --- ポート3000 --- ❌ (競合発生)

2. よくある発生シナリオ

このエラーは特に以下のようなシナリオで発生します。

  1. サーバーを終了せずに再起動しようとした
    • Ctrl+C を押し忘れたり、ターミナルを閉じてもバックグラウンドにプロセスが残っている場合に起きます。
  2. 開発用に複数の Node.js サーバーを同じポートで立ち上げた
    • Express と Vite、あるいは別の API サーバーを同時に起動して競合するケースです。
  3. 外部アプリケーションが同じポートを利用している
    • 3000 や 8080 のようなよく使われるポート番号は、他の開発環境やアプリがすでに利用していることがあります。

これらの状況では、単純にポートが衝突しているため、明示的に解放するか、別のポートを利用する必要があります。

3. 使用中のポートを確認する方法

競合の原因を特定するには、まずどのプロセスがポートを利用しているかを調べます。OS によってコマンドが異なります。

macOS / Linux の場合

lsof -i :3000

これにより、ポート 3000 を利用しているプロセスの PID(プロセスID)が確認できます。

Windows の場合

netstat -ano | findstr :3000

その後、表示された PID をタスクマネージャーで確認すると、どのアプリケーションが使っているか分かります。

図解イメージ:

[ポート3000]
 ├─ プロセスID: 12345 (node)
 └─ プロセスID: 67890 (別アプリ)

4. 解決方法

原因が分かったら、適切に対処します。代表的な方法は以下の通りです。

  1. 不要なプロセスを終了する
    • macOS/Linux なら kill -9 <PID> で強制終了可能です。
    • Windows なら taskkill /PID <PID> /F を利用します。
  2. サーバーコードでポート番号を変更する
    • app.listen(3001) のように、利用可能なポートへ変更する方法です。
  3. server.close() を使って明示的にサーバーを停止する
    • Node.js 側でアプリを終了させるコードを追加することで、再起動時のポート競合を防げます。
const http = require('http');
const server = http.createServer((req, res) => {
  res.end('Hello World');
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

// 終了処理の例
process.on('SIGINT', () => {
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });
});

このようにサーバーを明示的に閉じることで、ポートの解放が確実に行われます。

5. より安全に開発するための工夫

EADDRINUSE エラーを防ぐには、開発フローに工夫を加えるのも効果的です。

  • 環境変数でポート番号を柔軟に変更できるようにする const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`Server running on ${PORT}`));
  • ポート使用状況を自動で確認するライブラリを導入する
    • 例: detect-port を使って空いているポートを自動検出する。
  • Docker コンテナで隔離する
    • ローカル環境での競合を避けるため、開発環境をコンテナ化するのも有効です。

図解イメージ:

[ローカルPC]
 ├─ Node.js API (3000)
 ├─ フロントエンド (5173)
 └─ Docker内サーバー (8080)

6. まとめ

本記事では、Node.js でよく発生する 「Error: listen EADDRINUSE: address already in use」 エラーについて解説しました。主なポイントは以下の通りです。

  • 原因は ポート競合。サーバーが終了していないか、別のプロセスが同じポートを使用中。
  • lsofnetstat を使って競合プロセスを確認できる。
  • 解決策は プロセスの終了、ポート変更、server.close() の利用 など。
  • 開発フローに工夫を取り入れることで、同様のトラブルを未然に防ぐことが可能。

ポート競合は単純な問題ですが、初めて遭遇すると時間を浪費しがちです。正しい原因調査と解決法を理解しておけば、スムーズに開発を進めることができるでしょう。

参考

タイトルとURLをコピーしました