
元記事(Docker Networking Explained)の内容を、よりわかりやすく整理しました。
なぜDockerのネットワークを理解すべきか?
最初は docker run -p 3000:3000 my-app の一行でうまくいく。
でも、PostgresやRedisを追加した途端にこんなエラーが出る。
ECONNREFUSED 127.0.0.1:5432
ラップトップでは動いていたのに、なぜ?
それがDockerネットワークの核心的な問題です。
コンテナは「自分だけの世界」を持っている
各コンテナは独自のネットワーク空間(ネットワーク名前空間)を持ちます。
- 独自のIPアドレス
- 独自のルーティングテーブル
- 独自の
localhost
重要:コンテナ内の localhost = そのコンテナ自身であり、ホストPCでも他のコンテナでもない。
ブリッジネットワーク(Bridge Network)
DockerのデフォルトはLinuxの「ブリッジ」という仮想スイッチで各コンテナを繋ぐ方式。
コンテナ eth0
│
仮想イーサネットペア
│
Docker ブリッジ(docker0)
│
ホストのネットワーク
コンテナは 172.17.0.0/16 のようなプライベートIPをもらいます。
外部からは直接アクセスできません。
ポートの公開(Published Ports)
docker run -p 8080:80 nginx
これは「ホストの8080番ポートをコンテナの80番に転送する」という意味。
http://localhost:8080 → ホストの8080 → コンテナの80
同じホストポートを2つのコンテナで使うと競合してエラーになります。
コンテナポートは同じでも、ホストポートは違う番号にする必要があります。
ユーザー定義ブリッジ(推奨)
Docker標準のブリッジより、自分で作ったネットワークを使うのがおすすめ
docker network create app-network
docker run -d --name postgres --network app-network postgres:16
docker run -d --name api --network app-network -p 3000:3000 my-api
これでAPIコンテナは postgres:5432 というコンテナ名でDNS解決できるようになります。
| 接続先 | 使うべきアドレス |
|---|---|
| ホストPC → コンテナ | localhost:公開ポート番号 |
| コンテナ → コンテナ | サービス名:コンテナポート |
| コンテナ → 自分自身 | localhost |
ローカルホストの罠(最重要!)
これが最もよくある問題です。
# ❌ 間違い(API コンテナ内の localhost = API コンテナ自身)
DATABASE_URL=postgres://user:pass@localhost:5432/app
# ✅ 正解(コンテナ名 or Composeサービス名を使う)
DATABASE_URL=postgres://user:pass@postgres:5432/app
Docker Composeのネットワーク
Composeは自動でプロジェクト専用のネットワークを作ってくれます。
yaml
services:
api:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://postgres:secret@db:5432/app # ← "db"はサービス名
depends_on:
- db
db:
image: postgres:16
# ポートを外部公開しない → セキュア
プロダクション的な構成の鉄則: エッジのサービス(NginxやAPIゲートウェイ)だけ公開し
DB・キャッシュ・内部APIは非公開のまま。
yaml
services:
nginx: # ← 唯一の公開サービス
ports: ["80:80"]
api: # ← 外部公開なし(Nginxが内部でapi:3000に転送)
build: ./api
db: # ← 外部公開なし
image: postgres:16
0.0.0.0 へのバインド
ポートマッピングが正しいのにアクセスできない場合
アプリが 127.0.0.1 にしかバインドしていない可能性があります。
# ❌ これだとコンテナ内からしかアクセスできない
server listening on 127.0.0.1:3000
# ✅ すべてのインターフェースで受け付ける
server listening on 0.0.0.0:3000
ホストマシンへのアクセス
コンテナからPC上のサービス(モックサーバーなど)に接続したい場合
- Docker Desktop(Mac/Windows):
host.docker.internalがそのまま使える - Linux:明示的に指定が必要
docker run --add-host=host.docker.internal:host-gateway my-app
その他のネットワークモード
| モード | 概要 |
|---|---|
bridge | デフォルト。ほとんどの用途に対応 |
host | コンテナとホストがネットワーク共有。Dockerの分離なし |
none | ネットワーク完全遮断。バッチ処理など |
overlay | Swarm複数ホスト間の通信 |
macvlan | コンテナに物理ネットワーク上のIPを付与 |
トラブルシューティング
# ネットワーク確認
docker network ls
docker network inspect app-network
# コンテナに入る
docker exec -it api sh
# DNS解決確認
getent hosts db
# ポート確認
nc -vz db 5432
# HTTP確認
curl http://api:3000/health
# 公開ポート一覧
docker ps
デバッグ時のチェックリスト
- クライアントはどこで動いているか?
- サーバーはどこで動いているか?
- 同じDockerネットワークにいるか?
- サーバーは
0.0.0.0でリッスンしているか? - 通信の方向(内部 / ホスト→コンテナ / コンテナ→ホスト)は?
まとめ
「誰が、誰と話すべきか?」 — これが設計の出発点
- 各コンテナは独自の
localhostを持つ - コンテナ同士はサービス名で通信する
- ホストはポート公開を通じてコンテナと通信する
- エッジサービスだけ公開し、DB・内部APIは非公開を維持する


コメント