インフラ作業支援ラボInfra Support Lab ← ガイド一覧← 戻る

Dockerのport is already allocated・address already in useの原因と対処

port is already allocatedやbind: address already in useでコンテナが起動できない場合に、ホスト側の待ち受けとDockerのポート公開設定を分けて確認する障害ガイドです。

この記事の目的

競合しているホストポート・IP・プロセスを特定し、既存サービスを停止せず変更案を判断します。

まず確認すること

docker context show→docker ps --format→daemonホスト上でss -lntpでDockerとホスト側の利用状況を調べます。

本番作業前:既存プロセスをkillしたり、ポート公開範囲を不用意に広げたりしないでください。 web01・app-data・ポート番号などは説明用です。Docker context・対象コンテナ・データ保存先を照合してください。

1. このエラーはどこで起きるか

DockerがコンテナのポートをホストIP・ホストポートに公開しようとした際、競合やバインド制約で失敗することがあります。たとえば-p 8080:80はホスト側8080番からコンテナ側80番へ転送する指定です。調査対象は原則としてホスト側8080番です。

確認ポイント:コンテナ内アプリのaddress already in useは、同じコンテナ内部での二重起動等が原因の場合もあります。その場合はコンテナ起動失敗の記事でアプリログを確認します。

2. 読み取りコマンドだけで競合を調査

# Docker操作先が意図したホストか確認 docker context show # 公開済みのホストポート一覧 docker ps --format 'table {{.Names}}\t{{.Ports}}' # ホストのTCP待ち受けとプロセス(権限によってPIDは見えない) ss -lntp # 8080番のTCP待ち受けに絞る ss -lntp '( sport = :8080 )'

リモートDockerではCLI端末上ではなくdaemonホスト上でssを実行します。ssで競合元が表示されない場合も、Dockerがポート予約を持っていることがあります。また、IPv4/IPv6、指定したbindアドレス、ホストネットワークの設定によって結果の解釈が変わります。

3. コンテナが占有している場合

docker ps -a # 対象コンテナ名を実際のものへ置換 docker port web01 # Compose構成の解決結果(機密値の出力に注意) docker compose config --format json

Compose設定が複数ファイルに分かれている場合は、実際に起動するディレクトリと-f指定、プロジェクト名を合わせて確認します。docker compose configは環境変数を展開した内容が出るため、共有時は秘匿情報を伏せてください。

4. プロトコル・公開IPの確認漏れを防ぐ

# 参照のみ:IPv4/IPv6とTCP/UDPの双方を表示 ss -lntp ss -lnup # 公開アドレスとプロトコルを確認 docker ps --format 'table {{.Names}}\t{{.Ports}}' docker port web01

ssで待ち受けが見えなくても、Docker側の公開設定や、操作先が別のDocker contextである可能性を排除できません。8080:80は通常TCPを意味しますが、UDPを利用する場合は指定と確認コマンドの双方でプロトコルをそろえます。IPv6や特定IPのみの待ち受けを、IPv4全体の競合と混同しないでください。

ポート変更後は、対象サービスの待ち受けだけでなく、既存クライアント、リバースプロキシ、監視設定、外部公開の必要性まで確認します。既存プロセスのkillは自動対処に含めません。

5. 解消の選択肢を比較する

対応案効果本番確認
ホストポートを変更既存利用者への干渉を避けられる場合があるLB・Firewall・監視・接続先変更が必要
既存サービスを停止ポートが解放される可能性既存業務の停止影響・依存関係の確認が必要
別IPへ限定して公開同じポートを別IPで利用できる場合があるNIC・bind・Firewall・到達性を検証
不要なコンテナの整理意図せず残っていた公開設定を解消本当に不要か、データが残るかを確認

検証用の公開例は127.0.0.1:8081:80のようにlocalhostへ限定できますが、利用者が外部から接続する要件には適しません。業務要件に応じて設計します。

バージョン差:Docker Engine 28.0.0より古いバージョンでは、localhostに公開したポートへ同一L2セグメントの別ホストから到達できる場合があります。127.0.0.1指定だけで完全に隔離されると判断せず、Engineのバージョン・ホストのネットワーク・Firewallを確認してください。Docker公式の注意事項を参照。

6. bindできても外部接続できない場合

ポート競合エラーがなくても、通信できるとは限りません。待ち受けアドレス・Firewall・DockerのNAT/フィルター・リバースプロキシ・コンテナアプリのポートを区別して調べます。

Linux側の到達性はネットワーク疎通・接続障害ガイドを参照。Dockerはホストのファイアウォールルールへ影響するため、公開ポートの設定変更にはセキュリティ監査が必要です。

7. 修正後の確認・再発防止

docker ps --format 'table {{.Names}}\t{{.Ports}}' ss -lntp # localhostに公開した検証構成のみ curl -I http://127.0.0.1:8081/

起動成功だけでなく、外部から到達可能であるべき範囲と実際の公開範囲が一致しているかを確認します。ポート番号の割り当て台帳を管理し、変更前の使用状況を記録してください。

8. ポート競合の原因別に設定を直す

同じ8080番の競合でも、ホスト側プロセスが占有している場合と別コンテナが公開している場合では操作対象が異なります。以下は説明用の出力例であり、実機実測ではありません。

$ ss -lntp '( sport = :8080 )' LISTEN 0 511 127.0.0.1:8080 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
確認した結果安全な対応の選び方
ホストのnginx等が8080を使用業務サービスなら停止しない。新しいコンテナのホスト側公開ポートを変更できるか検討
既存Dockerコンテナが8080を公開所有プロジェクト・サービスへの接続を確認。不要と確定していないコンテナを削除しない
TCPのssに表示されないがbindに失敗IPv6/UDP、別context、公開IP、daemonの状態・ログを調査。TCPだけで空きと判断しない
bindできるが外部から接続不能競合とは別問題。公開先IP、アプリlisten、Firewall・Proxyを確認し、ネットワーク疎通ガイドへ

検証用nginxのComposeをlocalhostの8081へ変更する設定例です。実務上の公開範囲はセキュリティ要件に合わせて判断してください。

services: web: image: nginx:stable-alpine ports: - "127.0.0.1:8081:80"
# 読み取り:構成と対象プロジェクト docker compose config -q docker compose ps -a # 承認・影響確認後の適用操作 # docker compose up -d # 読み取り:反映後 docker compose ps -a ss -lntp curl -fI http://127.0.0.1:8081/
実行条件:公開ポートを変更すると、コンテナの再作成やLB・Proxy・監視の設定変更が必要になる場合があります。変更前のCompose定義を保存し、旧設定へ戻す場合も同様に再適用・再確認が必要です。

9. ポート変更後の成功・失敗判定

curlが成功しても、意図せず外部へ公開されていればセキュリティ上は不合格です。サービスの正常性と公開範囲は分けて検証します。

確認結果判定と次の行動
localhostのcurl成功、Dockerの公開先も想定どおりローカル疎通は成功候補。外部非公開が要件なら別ホストから到達しないことも確認
0.0.0.0:8081等の広い公開になっている設計に反する場合は不合格。公開IP、Firewall、Docker Engineのバージョンを確認して修正
新ポートの疎通は成功したが旧利用者は失敗LB・Proxy・クライアント接続先の切替が未完了。影響先を調査し、必要なら旧設定へ切り戻す
コンテナ自体が起動しない起動失敗の診断へ。ポート変更だけで解決したと判断しない
Docker Engineの旧版:28.0.0未満ではlocalhost公開であっても同一L2内からアクセスできる場合があります。IP指定だけで外部隔離を保証しないでください。

公式・一次資料

対象と実行前チェックを継続する

読み取り操作、設定変更、削除操作を分け、作業後の状態と業務影響を確認します。

柱ガイドへ戻る