はじめに

Docker でコンテナの起動時に以下のようなエラーが生じました。

docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint conflict-test (c73c99ba5cbaeac0c0ce83e5cfeffc0354d68843ed320c4bfcea37ad05f26bd1): failed to bind host port for 0.0.0.0:8080:172.17.0.2:8080/tcp: address already in use

エラーメッセージを確認すると、ホスト側の8080ポートがすでに別のプロセスによって使用されているため、コンテナのポート割り当てに失敗していることが分かります。

今回は、どのプロセスが対象のポートを使用しているのかを調査し、ポート競合の原因を特定する方法について紹介します。

ポートの競合が発生する理由

同じIPアドレス・ポート番号の組み合わせを複数のプロセスが同時に待ち受けることはできません。

例) アプリケーションA が ホスト側8080番ポート を使用していると、Dookcer コンテナに ホスト側8080番ポート を割り当てることができません。

競合したポートの調査

調査対象ポートを使用しているプロセスの特定

lsof -i :8080
COMMAND     PID          USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
python3 2043035 john-doe    3u  IPv4 10809101      0t0  TCP *:http-alt (LISTEN)

プロセスID からプロセスの詳細を確認する

ps -fp コマンドでプロセスの詳細を確認する。

ps -fp 2043035
UID          PID    PPID  C STIME TTY          TIME CMD
john-d+ 2043035 2040514  0 13:27 pts/0    00:00:00 python3 -m http.server 8080

すると、python3 -m http.server 8080 で簡易サーバーを起動しており、これが、:8080が利用していることがわかりました。

プロセスを kill する

python3 -m http.server 8080 が使用されていない前提で記述します。プロセスを kill するかは読者様の判断に任せます。

先程の調査で判明したプロセス ID を指定して kill を実行します。

kill 2043035

プロセスが 消えたことを確認する

コマンドを実行して出力がなければ、プロセスのkill が成功しています。

ps -fp 2043035

コンテナの起動

プロセスが kill されたので、ホスト側8080番ポート でコンテナを起動します。

$ docker run -d -p 8080:80 --name test-image test
4e6581f468b0f6e865b00710c237aa44591a93080276ed0b6a8e4b5c412fa16e

問題なく起動されていることがわかります。

$ docker ps
CONTAINER ID   IMAGE                  COMMAND                   CREATED          STATUS          PORTS                                               NAMES
4e6581f468b0   test                   "node ./app.js"           13 seconds ago   Up 13 seconds   8080/tcp, 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   test-image

おわりに

今回は、Dockerのコンテナ起動時に発生したポート競合エラーを例に、Linux上で使用中のポートを調査する方法について紹介しました。

ポート競合が発生した場合は、以下の流れで原因を特定できます。

  1. lsofコマンドで対象ポートを使用しているプロセスを特定する
  2. psコマンドでプロセスの詳細を確認する
  3. 不要なプロセスであればkillコマンドで停止する

Docker環境では、ローカル開発中に以前起動したコンテナやアプリケーションがポートを占有しているケースがあります。

エラーメッセージだけを見ると原因が分かりづらい場合もありますが、使用中のポートとプロセスを順番に確認することで、原因を切り分けることができます。

Linux環境でサービスやコンテナのトラブルシューティングを行う際は、今回紹介した調査手順を活用してみてください。