※本ページにはプロモーション(広告)が含まれています
Docker Composeでコンテナを起動しようとしたら「Bind for 0.0.0.0:XXXX failed: port is already allocated」というエラーが表示されて困っていませんか?
ポート競合エラーは、Docker Composeを使った開発で最も頻繁に遭遇するトラブルの一つです。特に複数のプロジェクトを並行して開発している場合や、ローカルで別のサービスが同じポートを使用している場合に発生しやすくなります。
この記事では、Docker Composeのポート競合エラーの原因を徹底的に分析し、初心者でも確実に解決できる対処法をステップバイステップで解説します。2026年最新のDocker Desktop環境にも完全対応しています。

この記事でわかること
- Docker Composeでポート競合エラーが発生する5つの主な原因
- 使用中のポートを特定して解放する具体的な手順
- docker-compose.ymlでのポート設定の正しい書き方
- 複数プロジェクトを安全に共存させるベストプラクティス
- 再発を防止するための環境構築テクニック
Docker Composeのポート競合エラーとは?基本を理解しよう
Docker Composeのポート競合エラーは、コンテナが使おうとしているホスト側のポートが、すでに別のプロセスやコンテナによって使用されている場合に発生します。
よく表示されるエラーメッセージ
ポート競合が発生した際には、以下のようなエラーメッセージが表示されます。
| エラーメッセージ | 意味 |
|---|---|
| Bind for 0.0.0.0:8080 failed: port is already allocated | ポート8080が既に使用中 |
| Error starting userland proxy: listen tcp4 0.0.0.0:3306: bind: address already in use | TCP 3306が別プロセスに占有されている |
| driver failed programming external connectivity | ネットワーク接続の確立に失敗 |
ポートバインドの仕組み
Docker Composeのports設定は「ホスト側ポート:コンテナ側ポート」の形式で記述します。例えば"8080:80"と書くと、ホストマシンの8080番ポートへのアクセスがコンテナ内の80番ポートに転送されます。
ホスト側のポートはOS上で一意である必要があるため、同じポート番号を複数のプロセスが同時に使用することはできません。これがポート競合の根本的な原因です。
ポート競合エラーが発生する5つの主な原因
原因1:ローカルで同じポートを使うサービスが起動している
最も多い原因が、ローカルマシン上で動いている別のサービスとの競合です。例えば、ローカルにインストールしたMySQLがポート3306を使用している状態で、Docker ComposeでもMySQLコンテナをポート3306で起動しようとするとエラーになります。
よく競合するサービスの組み合わせは以下の通りです。
| ポート番号 | よく使うサービス | 競合しやすいケース |
|---|---|---|
| 80 / 443 | Apache、Nginx | ローカルWebサーバーとDocker Webコンテナ |
| 3306 | MySQL | ローカルMySQLとDockerのMySQLコンテナ |
| 5432 | PostgreSQL | ローカルPostgreSQLとDockerのPGコンテナ |
| 6379 | Redis | ローカルRedisとDockerのRedisコンテナ |
| 8080 | 開発サーバー全般 | 複数の開発プロジェクトが同時起動 |
原因2:停止し忘れた別のDocker Composeプロジェクト
別のプロジェクトのDocker Composeをdocker compose downせずに放置していると、そのコンテナがポートを占有し続けます。特に複数のプロジェクトで同じデフォルトポート(80、3306、5432など)を使っている場合に頻発します。
原因3:docker compose downが不完全だった
docker compose downを実行しても、ネットワークやボリュームが残ってしまうことがあります。また、コンテナが正常に停止されず「ゾンビコンテナ」として残る場合もあります。
原因4:Docker Desktop自体の不具合
Docker Desktopのバージョンアップ後や、マシンのスリープ復帰後にDockerデーモンが不安定になり、以前のポートバインドが正しく解放されないことがあります。
原因5:docker-compose.ymlのポート設定ミス
YAML構文の問題で意図しないポート設定になるケースもあります。例えば、ポート番号をクォーテーションで囲まないと、YAMLパーサーが数値として解釈してしまう場合があります。

対処法1:使用中のポートを特定して解放する
まず、どのプロセスが該当ポートを使用しているかを特定し、安全に解放する手順を解説します。
ステップ1:ポートを使用しているプロセスを特定する
macOSの場合:
ターミナルで以下のコマンドを実行します。例としてポート8080を調べる場合です。
lsof -i :8080
出力例として、PID(プロセスID)とプロセス名が表示されます。このPIDを使ってプロセスを終了できます。
Windowsの場合:
netstat -ano | findstr :8080
Linuxの場合:
ss -tlnp | grep 8080
ステップ2:不要なプロセスを停止する
特定したプロセスが不要なものであれば、以下のコマンドで停止します。
macOS / Linuxの場合:
kill -9 [PID番号]
Windowsの場合:
taskkill /PID [PID番号] /F
⚠️ プロセスを終了する前に、そのプロセスが何のサービスかを必ず確認してください。システムに必要なプロセスを誤って終了すると、別の問題が発生する可能性があります。
ステップ3:Dockerコンテナがポートを占有している場合
別のDockerコンテナがポートを使用している場合は、以下のコマンドで確認・停止します。
# 実行中のコンテナ一覧とポートマッピングを確認
docker ps --format "table {{.Names}}\t{{.Ports}}"
# 特定のコンテナを停止
docker stop [コンテナ名またはID]
# 停止済みコンテナも含めて全一覧を表示
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
対処法2:docker-compose.ymlのポート設定を変更する
ポートを解放できない場合や、ローカルサービスと共存させたい場合は、Docker Compose側のポート設定を変更します。
ステップ1:ホスト側ポートを別の番号に変更する
docker-compose.ymlのportsセクションで、ホスト側(左側)のポート番号だけを変更します。コンテナ内部のポートはそのままで問題ありません。
# 変更前(ポート8080が競合)
services:
web:
image: nginx
ports:
- "8080:80"
# 変更後(ホスト側を8081に変更)
services:
web:
image: nginx
ports:
- "8081:80"
ステップ2:環境変数でポートを管理する
プロジェクトごとにポートを柔軟に変更できるよう、.envファイルと環境変数を活用しましょう。
.envファイル:
WEB_PORT=8081
DB_PORT=3307
REDIS_PORT=6380
docker-compose.yml:
services:
web:
image: nginx
ports:
- "${WEB_PORT:-8080}:80"
db:
image: mysql:8.0
ports:
- "${DB_PORT:-3306}:3306"
redis:
image: redis:alpine
ports:
- "${REDIS_PORT:-6379}:6379"
この方法なら、プロジェクトごとに.envファイルでポートを設定でき、競合を簡単に回避できます。:-の後の数値はデフォルト値です。
ステップ3:ポートバインドをlocalhostに限定する
セキュリティの観点からも、ポートバインドをlocalhostに限定することをおすすめします。
services:
web:
ports:
- "127.0.0.1:8080:80" # localhostからのみアクセス可能
対処法3:停止し忘れたコンテナを一括クリーンアップする
ステップ1:全プロジェクトのコンテナ状況を確認する
# 実行中の全コンテナを確認
docker ps
# 停止中も含めた全コンテナを確認
docker ps -a
ステップ2:不要なコンテナ・ネットワーク・ボリュームを削除する
# 特定プロジェクトのコンテナを停止・削除
cd /path/to/project
docker compose down
# ボリュームも含めて完全削除(データも消える点に注意)
docker compose down -v
# 未使用のDockerリソースを一括削除
docker system prune
⚠️ docker system pruneは未使用のコンテナ、ネットワーク、イメージを削除します。必要なリソースが消えないか確認してから実行してください。
ステップ3:ゾンビプロセスを強制終了する
稀にDockerのプロキシプロセスが残ってしまうことがあります。
# docker-proxyプロセスを確認(macOS/Linux)
ps aux | grep docker-proxy
# 該当プロセスがあれば停止
kill -9 [PID]

対処法4:Docker Desktopを再起動する
Docker Desktop自体の不具合が原因の場合、再起動で解決することが多いです。
ステップ1:Docker Desktopを完全に終了する
macOS:メニューバーのDockerアイコン → 「Quit Docker Desktop」をクリック
Windows:タスクトレイのDockerアイコン → 右クリック → 「Quit Docker Desktop」
ステップ2:Dockerプロセスが完全に終了したか確認する
# macOS
ps aux | grep -i docker
# Windows(PowerShell)
Get-Process | Where-Object {$_.Name -like "*docker*"}
残っているDockerプロセスがあれば強制終了します。
ステップ3:Docker Desktopを再起動する
完全に終了したことを確認してから、Docker Desktopを再度起動します。起動完了後(タスクバーのアイコンが安定するまで待つ)、再度docker compose upを試します。
対処法5:Docker Composeのネットワーク設定を見直す
ステップ1:カスタムネットワークを確認する
# Dockerネットワーク一覧
docker network ls
# 不要なネットワークを削除
docker network prune
ステップ2:プロジェクト間でネットワークを分離する
複数プロジェクトが同じネットワーク名を使用すると問題が発生することがあります。docker-compose.ymlでプロジェクト固有のネットワーク名を指定しましょう。
services:
web:
networks:
- myproject-network
networks:
myproject-network:
name: myproject-custom-network
対処法6:ポートを使わずにDockerネットワーク内で通信する
そもそもホストへのポート公開が不要な場合は、portsの代わりにexposeを使うことでポート競合を完全に回避できます。
services:
web:
image: nginx
ports:
- "8080:80" # ホストからアクセスが必要なのはWebだけ
app:
image: node:18
expose:
- "3000" # コンテナ間通信のみ(ホストには公開しない)
db:
image: mysql:8.0
expose:
- "3306" # コンテナ間通信のみ
この構成なら、DBやアプリサーバーのポートがホスト側で競合する心配がありません。同じDockerネットワーク内のコンテナ同士は、サービス名をホスト名として通信できます。
再発防止のベストプラクティス
| 対策 | 内容 | 効果 |
|---|---|---|
| .envファイルでポート管理 | プロジェクトごとに異なるポートを設定 | 複数プロジェクトの共存が容易に |
| ポート規則を決める | プロジェクトA=8080番台、B=8090番台など | チーム内での競合を防止 |
| exposeを活用する | 外部アクセス不要なサービスはexpose | ポート競合リスクを根本的に排除 |
| 作業終了時にdown | docker compose downを習慣化 | 放置コンテナによる競合を防止 |
| ローカルサービスをDockerに統一 | MySQL等もDocker経由で使う | ローカルサービスとの競合を排除 |
この記事に関連するおすすめ商品
Docker&仮想サーバー完全入門(技術書)
約3,520円
Docker Composeの基礎から実践まで網羅した定番書籍
USB-C ドッキングステーション(開発環境用)
約6,980円
マルチモニター+有線LAN接続で安定した開発環境を構築
外付けSSD 1TB(開発用ストレージ)
約9,980円
Dockerイメージの保管に最適な高速ポータブルSSD
※ 価格は変動します。最新価格はリンク先でご確認ください
よくある質問(FAQ)
Q. docker compose upで「port is already allocated」と出ました。原因は?
ホスト側で指定したポート番号が、別のプロセスやコンテナによって既に使用されています。lsof -i :ポート番号(macOS/Linux)で使用中のプロセスを特定し、停止するか、docker-compose.ymlのホスト側ポートを別の番号に変更してください。
Q. docker compose downしてもポートが解放されません
Docker Desktopのプロキシプロセスが残っている可能性があります。Docker Desktopを完全に終了して再起動するか、docker system pruneで未使用リソースをクリーンアップしてください。
Q. 複数プロジェクトを同時に起動するにはどうすればいい?
各プロジェクトの.envファイルで異なるポート番号を設定します。例えばプロジェクトAはWEB_PORT=8080、プロジェクトBはWEB_PORT=8090のように分けると、同時に起動しても競合しません。
Q. portsとexposeの違いは何ですか?
portsはホストマシンにポートを公開するため、ブラウザなどの外部からアクセスできます。exposeはDockerネットワーク内のコンテナ間通信のみに使用され、ホスト側にポートを公開しません。ポート競合の心配がないのはexposeです。
Q. Docker Desktop for Macでポート80を使おうとするとPermission deniedになります
1024番以下のポートは特権ポートのため、管理者権限が必要です。開発環境では8080や3000など1024以上のポートを使用することをおすすめします。どうしても80番を使いたい場合は、sudoでDocker Desktopを起動する必要があります。
Q. docker compose up -dで起動してもすぐにコンテナが停止してしまいます
ポート競合以外の原因(アプリケーションエラーなど)も考えられます。docker compose logs [サービス名]でログを確認し、具体的なエラーメッセージを確認してください。ポート競合の場合は「address already in use」というメッセージが含まれます。
Q. WSL2環境でWindowsのサービスとDockerコンテナのポートが競合します
WSL2ではWindowsホストのポートとLinux側のポートが共有されるため、Windows上で動いているサービス(IIS、SQL Serverなど)とDockerコンテナのポートが競合しやすくなります。Windowsサービスを停止するか、Dockerコンテナのホスト側ポートを変更してください。
まとめ
Docker Composeのポート競合エラーは、原因を正しく特定できれば確実に解決できる問題です。以下のポイントを押さえておきましょう。
| 状況 | おすすめの対処法 |
|---|---|
| ローカルサービスと競合 | ローカルサービスを停止、またはホスト側ポートを変更 |
| 別プロジェクトのコンテナと競合 | 不要なプロジェクトをdocker compose down |
| ポートが解放されない | Docker Desktop再起動、docker system prune |
| 再発防止 | .envファイルでポート管理、exposeの活用 |
特に.envファイルによるポート管理とexposeの活用は、チーム開発でも個人開発でもぜひ取り入れていただきたいベストプラクティスです。ポート競合に悩まされない快適なDocker開発環境を構築しましょう。
minto.tech スマホ(Android/iPhone)・PC(Mac/Windows)の便利情報をお届け! 月間アクセス160万PV!スマートフォン、タブレット、パソコン、地デジに関する素朴な疑問や、困ったこと、ノウハウ、コツなどが満載のお助け記事サイトはこちら!