Docker ネットワークの仕組み — bridge / host / none を理解する
概要
Docker を使い始めると、「コンテナからホストのポートにつながらない」「コンテナ同士が名前で通信できない」といった問題に必ず一度はぶつかります。これらの大半は、Docker のネットワークドライバの挙動を理解していないことが原因です。
この記事では、Docker が標準で持つ3つのネットワークドライバ bridge / host / none を、仕組み・使いどころ・確認方法までまとめて整理します。入門者が「なんとなく動いている」状態を抜け出し、意図してネットワークを選べるようになることを目的とします。
前提環境
- Docker Engine 24 以降(Linux ホストを前提)
- 記事中のコマンドは Linux 上での挙動を基準にしています
- Docker Desktop(macOS / Windows)では Docker Engine が内部の Linux VM 上で動くため、一部の挙動が Linux ホストと異なります(後述)
ネットワークドライバとは何か
Docker のネットワークは「ドライバ」で抽象化されています。まずホストに最初から用意されているネットワークを確認します。
docker network ls
NETWORK ID NAME DRIVER SCOPE abc123456789 bridge bridge local def234567890 host host local ghi345678901 none null local
- bridge: デフォルト。仮想ブリッジを介してコンテナを隔離しつつ外部と通信する
- host: ホストのネットワークスタックをそのまま共有する
- none: ネットワークを一切持たせない
bridge ネットワーク
仕組み
ネットワークを指定せずに docker run すると、コンテナは bridge に接続されます。Docker はインストール時にホスト上へ docker0 という仮想ブリッジ(仮想的な L2 スイッチ)を作成し、各コンテナを仮想イーサネットペア(veth)で接続します。コンテナには 172.17.0.0/16 のようなプライベートIPが振られます。
[コンテナA] [コンテナB]
eth0(172.17.0.2) eth0(172.17.0.3)
| |
veth veth
| |
+---------- docker0 ----------+ ← 仮想ブリッジ
|
ホストの eth0
|
外部ネットワーク
外部への通信は、ホストの iptables による NAT(マスカレード)を通ります。つまり bridge は「隔離されているが、外には出られる」構成です。
デフォルト bridge とユーザー定義 bridge の違い
入門者が最もつまずくポイントです。デフォルトの bridge ネットワークでは、コンテナ同士をコンテナ名で名前解決できません。 一方、自分で作成した「ユーザー定義 bridge」では内蔵 DNS によってコンテナ名での通信ができます。
# ユーザー定義 bridge を作成 docker network create my-net # 2つのコンテナを同じネットワークにつなぐ docker run -d --name web --network my-net nginx docker run -it --rm --network my-net alpine sh # alpine コンテナ内から、コンテナ名で通信できる / # ping web PING web (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.1 ms
実運用やマルチコンテナ構成では、原則としてユーザー定義 bridge を使うのが鉄則です。Docker Compose がサービスを名前で解決できるのも、Compose が自動でユーザー定義ネットワークを作っているためです。
ポート公開(ポートフォワード)
bridge のコンテナはプライベートIPを持つため、外部から直接はアクセスできません。ホストのポートとコンテナのポートを -p で紐づけます。
# ホストの8080 → コンテナの80 へ転送 docker run -d -p 8080:80 nginx
ブラウザ → ホスト:8080 → (iptables NAT) → コンテナ:80
「コンテナを立てたのにアクセスできない」の多くは、この -p の付け忘れ、または左右(ホスト側:コンテナ側)の取り違えです。
host ネットワーク
仕組み
--network host を指定すると、コンテナは独自のネットワーク名前空間を持たず、ホストのネットワークスタックをそのまま共有します。コンテナ内で開いたポートは、そのままホストのポートになります。
docker run -d --network host nginx # -p を付けなくても、ホストの80番で直接 nginx にアクセスできる curl http://localhost:80
NAT もポートフォワードも挟まないため、ネットワークのオーバーヘッドが小さいのが利点です。
注意点
-pによるポートマッピングは無視されます(警告が出ます)- ホストとポートが衝突しやすくなります
- 隔離が弱くなるため、セキュリティ面では bridge より慎重に扱う必要があります
none ネットワーク
仕組み
--network none を指定すると、コンテナはループバック(lo)以外のネットワークインターフェースを一切持ちません。外部とも他コンテナとも通信できません。
docker run -it --rm --network none alpine sh / # ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> ... # eth0 は存在しない
使いどころ
- 外部通信が不要なバッチ処理・計算処理を、ネットワークから完全に隔離して走らせたい
- 信頼できないコードをサンドボックス的に実行したい
「通信させない」を明示的に選べることが、セキュリティ設計上の意味を持ちます。
3ドライバの比較
| 項目 | bridge | host | none |
|---|---|---|---|
| 隔離 | あり(独自IP) | なし(ホスト共有) | 完全隔離 |
| 外部との通信 | NAT 経由 | ホストそのまま | 不可 |
| ポート公開 | -p が必要 |
不要(自動) | 不可 |
| コンテナ間通信 | 可(ユーザー定義bridgeは名前解決も可) | ホスト経由 | 不可 |
| オーバーヘッド | あり(NAT) | 小さい | — |
| 主な用途 | 一般的なアプリ | 高スループット/ホスト密結合 | 隔離バッチ |
確認方法
ネットワークの中身は docker network inspect で確認できます。
docker network inspect bridge
[
{
"Name": "bridge",
"Driver": "bridge",
"IPAM": {
"Config": [{ "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" }]
},
"Containers": {
"abc...": { "Name": "web", "IPv4Address": "172.17.0.2/16" }
}
}
]
コンテナ内のインターフェースは docker exec <id> ip addr で確認します。
注意点
- Docker Desktop(macOS / Windows)の host は Linux と挙動が異なる: Docker Engine が VM 内で動くため、
--network hostを使ってもホストOS(macOS/Windows)のポートに直接は開かれません - デフォルト bridge では名前解決できない: マルチコンテナならユーザー定義 bridge(または Compose)を使うこと
- host はポート衝突に注意: 隔離がない分、ホスト環境との干渉が起きやすい
まとめ
- bridge: デフォルト。隔離しつつ NAT で外に出る。マルチコンテナならユーザー定義 bridge を使い、名前解決を効かせる
- host: ホストのネットワークを共有。オーバーヘッドが小さいがポート衝突と隔離低下に注意。Docker Desktop では挙動が違う
- none: 通信を一切持たせない。隔離したいバッチやサンドボックスに
「なぜつながらない / なぜ名前で引けない」の多くは、この3ドライバの違いを押さえれば説明がつきます。まずは docker network ls と docker network inspect で、自分のコンテナがどのネットワークにいるのかを確認する習慣をつけるのがおすすめです。
