症状
Docker コンテナ内からホストマシン上のサービス(localhost:3000 など)に接続できない。
結論:まずこれを確認
host.docker.internalを使っているか確認する- ホスト側のサービスが
127.0.0.1ではなく0.0.0.0でリッスンしているか確認する - ホスト側のファイアウォールがブロックしていないか確認する
トラブルシューティングフロー
flowchart TD
A[コンテナからホストに接続できない] --> B{どのアドレスを使用?}
B -->|localhost/127.0.0.1| C[host.docker.internalに変更]
B -->|host.docker.internal| D{名前解決できる?}
D -->|No| E[Docker Desktop確認/extra_hosts設定]
D -->|Yes| F{ホストのサービス起動中?}
F -->|No| G[サービスを起動]
F -->|Yes| H{0.0.0.0でリッスン?}
H -->|No| I[バインドアドレスを変更]
H -->|Yes| J{ファイアウォール?}
J -->|ブロック| K[ルールを追加]
J -->|許可済み| L[ネットワークモード確認]
よくある原因
- localhost/127.0.0.1 を直接指定している - コンテナ内の localhost はコンテナ自身を指す
- host.docker.internal が解決できない - Linux では追加設定が必要な場合がある
- ホストのサービスが 127.0.0.1 のみでリッスン - 外部からの接続を受け付けない設定
- ファイアウォールがブロック - iptables/ufw/firewalld がコンテナからの接続を遮断
- Docker ネットワークモードの問題 - bridge モードでのルーティング設定不備
- ホスト側のサービスが停止中 - そもそも接続先が起動していない
- ポート番号の間違い - コンテナ側で指定したポートが実際と異なる
確認手順
ステップ1: 接続先アドレスを確認する
コンテナ内から接続しようとしているアドレスを確認する。
# コンテナ内で実行
echo $DATABASE_URL
# または接続コマンドを確認
🔍 チェックポイント: localhost や 127.0.0.1 を使用している場合は host.docker.internal に変更する
ステップ2: host.docker.internal の名前解決を確認する
# コンテナ内で実行
ping host.docker.internal
# または
getent hosts host.docker.internal
🔍 チェックポイント: IP アドレスが返ってくれば名前解決は成功
Linux で解決できない場合の対処:
docker-compose.yml に以下を追加:
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
または docker run 時:
docker run --add-host=host.docker.internal:host-gateway イメージ名
ステップ3: ホスト側のサービス状態を確認する
# ホストで実行
# サービスが起動しているか
ss -tlnp | grep ポート番号
# または
netstat -tlnp | grep ポート番号
🔍 チェックポイント: 該当ポートで LISTEN 状態のプロセスが表示される
ステップ4: リッスンアドレスを確認する
# ホストで実行
ss -tlnp | grep ポート番号
出力例:
LISTEN 0 128 127.0.0.1:3000 *:* users:(("node",pid=1234,fd=10))
🔍 チェックポイント: 127.0.0.1:ポート ではなく 0.0.0.0:ポート または *:ポート であること
127.0.0.1 の場合の対処:
サービスの設定でバインドアドレスを変更する:
# 例: Node.js
app.listen(3000, '0.0.0.0')
# 例: Python Flask
app.run(host='0.0.0.0', port=3000)
ステップ5: ファイアウォールを確認する
# ホストで実行(Linux)
# iptables の場合
sudo iptables -L -n | grep ポート番号
# ufw の場合
sudo ufw status
# firewalld の場合
sudo firewall-cmd --list-all
🔍 チェックポイント: Docker ネットワーク(通常 172.17.0.0/16)からの接続が許可されている
ステップ6: コンテナから接続テストを行う
# コンテナ内で実行
# curl がある場合
curl -v http://host.docker.internal:ポート番号
# nc がある場合
nc -zv host.docker.internal ポート番号
# telnet がある場合
telnet host.docker.internal ポート番号
🔍 チェックポイント: 接続が確立されること(Connection refused や timeout ではない)
NG行動(やってはいけないこと)
- –network=host を安易に使う - セキュリティリスクが高く、ポートの分離ができなくなる
- ファイアウォールを全面的に無効化する - セキュリティ上問題。必要なルールのみ追加する
- 0.0.0.0 でリッスンしたまま本番環境にデプロイ - 意図しない外部公開につながる可能性がある
- コンテナ内から直接ホストの IP を指定する - 環境依存になり移植性が下がる
よくある質問(FAQ)
Q1: host.docker.internal は Docker Desktop 以外でも使える?
A: Linux ではデフォルトで使えない場合がある。--add-host=host.docker.internal:host-gateway オプションまたは docker-compose.yml の extra_hosts 設定が必要。Docker Engine 20.10 以降で対応。
Q2: WSL2 環境で接続できない場合は?
A: WSL2 では追加のネットワーク設定が必要な場合がある。Docker Desktop for Windows を使用している場合は host.docker.internal が自動設定される。WSL2 内で Docker Engine を直接使用している場合は extra_hosts 設定を追加する。
Q3: コンテナ同士の通信も同じ方法?
A: コンテナ同士は同じ Docker ネットワーク内であればサービス名で通信できる。host.docker.internal はホストマシンへの接続専用。
関連するエラー・症状
- (関連記事準備中)
- (関連記事準備中)
- (関連記事準備中)
解決しない場合
公式ドキュメント
確認すべきログ
# Docker デーモンログ
sudo journalctl -u docker.service
# コンテナログ
docker logs コンテナ名
次に調べるキーワード
docker bridge network routingdocker iptables rulesdocker host networking mode