ネットワークを使い分ける - bridge / host / overlay
Docker のネットワークドライバは bridge・host・overlay などに分かれ、用途が違う。user-defined bridge では DNS 解決が働き、`--network host` は Linux と Docker Desktop で挙動が大きく異なる。
概念図
構文
docker network create [--driver bridge|overlay] <name>
docker run --network <name|host> <image>実例
user-defined bridge でサービス名 DNS 解決を使う
docker network create appnet
docker run -d --name db --network appnet postgres:16
docker run -d --name api --network appnet myorg/api
# api コンテナから "db" でアクセスできる / api can reach "db" by namecompose で frontend / backend をネットワーク分離する
services:
web:
image: nginx
networks:
- frontend
api:
image: myorg/api
networks:
- frontend
- backend
db:
image: postgres:16
networks:
- backend
networks:
frontend:
backend:ドライバの違い(bridge / host / overlay / none)
| ドライバ | 範囲 | 主な用途 | 備考 |
|---|---|---|---|
bridge |
単一ホスト | 既定。コンテナ間通信 + NAT 外向き | user-defined bridge は DNS 付き |
host |
単一ホスト | ホストのネットスタック直接利用 | Linux 限定。Desktop は VM 越しで別挙動 |
overlay |
複数ホスト | Swarm などで L2 仮想ネット張る | Swarm / KV ストア前提 |
none |
なし | 外部通信を完全遮断 | ネットワーク不要なジョブ向け |
開発で意識するのはほぼ bridge と host の 2 つ。
Compose でネットワークを明示しない場合、プロジェクトごとに専用の user-defined bridge が自動で作られる。
user-defined bridge で DNS 解決
Docker の既定 bridge(bridge という名前そのもの)には歴史的経緯で DNS 機能が付いておらず、--link を使う必要がある。
対して docker network create や Compose で作られる user-defined bridge は内蔵 DNS が動き、同じネットワーク上のコンテナは「サービス名」や「コンテナ名」で相互に名前解決できる。
これにより api コンテナから db:5432 のような接続文字列がそのまま動作する。
複数のサービス群を論理的に分離したいときは、frontend と backend のように複数の user-defined bridge を作ってサービスを所属させると、API だけが両方に属してプロキシ役になる構成を安全に組める。
DB を含む backend ネットワークを外から到達不能にすることで、攻撃面を減らせる。
`--network host` が OS ごとに挙動違う
Linux で --network host を指定すると、コンテナはホストと同じネットワークスタックを使う。
NAT を通らずポートが直接公開されるためベンチマーク用途では便利だが、ポート衝突やセキュリティ境界の消失というデメリットもある。
一方、Docker Desktop(macOS / Windows)は裏側で軽量 VM を動かしているため、host を指定してもホスト OS と同じ IP を共有するわけではなく、VM 内のネットワークをホストにする挙動になる。
結果として macOS で「Linux と同じだろう」と思って --network host を書くと、ホスト OS から localhost:8080 でアクセスできない、という事故が起こる。
Docker Desktop 側でも新しめのバージョンでは experimental な host ネットワーキング対応が入っているが、依然として Linux と同等ではないことを前提にすべき。
# Linux: ホストの :8080 にそのまま bind される
# Linux: binds directly to host :8080
docker run --rm --network host nginx
# Docker Desktop: VM 内の host であり macOS 本体ではない
# Docker Desktop: host of the VM, not the macOS itself関連トピック
host.docker.internal- コンテナから「ホスト側の localhost」に繋ぎたいときに使う特殊名。Docker Desktop では最初から解決できるが、Linux では `--add-host=host.docker.internal:host-gateway` を付ける必要がある。 docker compose- 複数コンテナをまとめて起動・停止するための compose.yml。services / networks / volumes の 3 ブロックで構成され、`docker compose up -d` と `docker compose down` が中心操作になる。 