12k
All articles

Node.jsにおける「listen EADDRINUSE: address already in use」エラーの解決方法

Node.jsのEADDRINUSEエラーの解決方法を解説。使用中のポートの特定、プロセスの終了、グレースフルシャットダウンの実装でポート競合を防ぐ。

OpenReplay Team
OpenReplay Team
Node.jsにおける「listen EADDRINUSE: address already in use」エラーの解決方法

予期しないタイミングで発生する厄介なEADDRINUSEエラー。Node.jsサーバーを起動しようとしたところ、アプリケーションが動作する代わりに次のようなエラーが表示されます:Error: listen EADDRINUSE: address already in use :::3000。このNode.js EADDRINUSEエラーは、バインドしようとしているポートが既に別のプロセスによって使用されていることを意味します。このNode.jsにおけるポート競合を迅速に特定して修正する方法を説明します。

重要なポイント

  • EADDRINUSEエラーは、ポートが既に別のプロセスによって占有されている場合に発生します
  • macOS/Linuxではlsof、Windowsではnetstatを使用してブロックしているプロセスを特定します
  • PIDを使用してプロセスを終了するか、グレースフルシャットダウンハンドラーを実装します
  • 動的ポート選択と適切なシグナルハンドリングで将来の競合を防止します

EADDRINUSEエラーの原因

listen EADDRINUSEエラーは、Node.jsアプリケーションが既に占有されているポートにバインドしようとしたときに発生します。よくある原因は以下の通りです:

  • サーバーの前のインスタンスがまだ実行中
  • 同じポートを使用している別のアプリケーション
  • クラッシュしたNode.jsアプリのゾンビプロセス
  • nodemonなどのホットリロードツールがクリーンアップに失敗
  • IDEの統合ターミナルがプロセスを維持している

ポートを使用しているプロセスの特定方法

占有されているポートを解放する前に、何がそれを使用しているかを特定する必要があります。コマンドはオペレーティングシステムによって異なります。

macOSとLinux

lsofを使用してプロセスを見つけます:

lsof -i :3000

これはPID(プロセスID)を含むプロセスの詳細を返します:

COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node     12345   you   11u  IPv6 0xac745b2749fd2be3      0t0  TCP *:3000 (LISTEN)

Windows

netstatを使用してプロセスを特定します:

netstat -ano | findstr :3000

出力の最後の列にPIDが表示されます:

TCP    0.0.0.0:3000    0.0.0.0:0    LISTENING    12345

プロセスを終了してポートを解放する方法

PIDを取得したら、プロセスを終了してポートを解放できます。

macOSとLinuxでの解決方法

クイックワンライナー:

lsof -ti:3000 | xargs kill -9

手動アプローチ:

kill -15 12345  # グレースフルシャットダウン(推奨)
kill -9 12345   # -15が機能しない場合は強制終了

fuserを使用する代替方法:

sudo fuser -k 3000/tcp

Windowsでの解決方法

コマンドプロンプト:

taskkill /PID 12345 /F

PowerShell:

Stop-Process -Id 12345 -Force

GUI方式: タスクマネージャー(Ctrl+Shift+Esc)を開き、Node.jsプロセスを見つけて終了します。

将来のポート競合を防ぐ

グレースフルシャットダウンの実装

Node.jsサーバーに適切なクリーンアップハンドラーを追加してポートエラーを防ぎます:

const server = app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

// 終了シグナルを処理
process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Server closed gracefully');
    process.exit(0);
  });
});

process.on('SIGINT', () => {
  server.close(() => {
    console.log('Server closed gracefully');
    process.exit(0);
  });
});

動的ポート選択の使用

ポートをハードコーディングしないでください。環境変数を使用するか、利用可能なポートを自動的に見つけます:

const PORT = process.env.PORT || 3000;

// またはバインド前にポートの可用性を確認
const net = require('net');

function getAvailablePort(startPort) {
  return new Promise((resolve) => {
    const server = net.createServer();
    server.listen(startPort, () => {
      const port = server.address().port;
      server.close(() => resolve(port));
    });
    server.on('error', () => {
      getAvailablePort(startPort + 1).then(resolve);
    });
  });
}

プログラムでエラーを処理

エラーをキャッチして適切に対応します:

server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error(`Port ${PORT} is already in use`);
    // 別のポートを試すか、グレースフルに終了
    process.exit(1);
  }
});

よくあるシナリオとクイックフィックス

nodemonがポートを解放しない

nodemonを使用している場合は、Ctrl+Zではなく、Ctrl+Cで停止していることを確認してください。Ctrl+Zはポートを解放せずにプロセスを一時停止します。

Dockerコンテナの競合

実行中のコンテナを確認します:

docker ps
docker stop <container_id>

VS Codeターミナルの問題

サーバーを再起動する前に、すべての統合ターミナルを閉じてください。VS Codeはバックグラウンドでプロセスを維持することがあります。

コード内の複数のサーバーインスタンス

コードベース内でapp.listen()を複数回呼び出していないことを確認してください。このよくある間違いは、アドレスが既に使用中エラーを即座に引き起こします。

まとめ

Node.js EADDRINUSEエラーは厄介ですが、簡単に修正できます。lsofまたはnetstatでポートを使用しているプロセスを見つけ、それを終了し、将来の発生を防ぐために適切なシャットダウンハンドラーを実装してください。覚えておいてください:シグナルハンドラーによるグレースフルシャットダウンと動的ポート選択により、このNode.jsサーバーポートエラーに繰り返し対処する必要がなくなります。

よくある質問

デフォルトポートが使用中の場合、自動的に別のポートに切り替えることはできますか?

はい、EADDRINUSEエラーをキャッチして次の利用可能なポートを試すことで、自動ポート切り替えを実装できます。再帰関数またはループを使用して、開いているポートが見つかるまでポートを順次テストするか、これを自動的に処理するportfinderなどのライブラリを使用します。

ターミナルを閉じた後もEADDRINUSEエラーが続くのはなぜですか?

ターミナルウィンドウを閉じても、実行中のプロセスが常に終了するわけではありません。特にnohupで起動されたプロセスやサービスとして起動されたバックグラウンドプロセスは実行を続けます。ポートが確実に解放されるように、常にCtrl+Cのような適切な終了コマンドを使用するか、PIDを使用してプロセスを明示的に終了してください。

-9でプロセスを終了するのはアプリケーションにとって安全ですか?

kill -9を使用すると、クリーンアップを許可せずに即座に終了するため、データの損失や破損を引き起こす可能性があります。グレースフルシャットダウンのために常に最初にkill -15を試してください。kill -9は応答しないプロセスのために予約してください。クリーンなシャットダウンを確保するために、コードに適切なシグナルハンドラーを実装してください。

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.