言語を切り替える
テーマを切り替える

Dockerネットワークモード完全解説:bridge/host/none/containerの4モード性能比較と使い分け

ターミナルに緑色の「Container started」が表示され、サービスは起動しているはずなのに、curlはタイムアウトのまま。docker logsを3回見てもエラーは出ない。-p 8080:80のポートマッピングも設定済み、ルーティングも問題なし、ファイアウォールもオフ。一体どこがおかしいのでしょうか?

原因はネットワークモードの選択ミスでした。docker run -pさえすれば十分だと思っていたのに、Dockerにはbridge、host、none、containerの4つのネットワークモードがあることを知りませんでした。

「コンテナは起動したのにアクセスできない」という経験がある方、あるいはDockerのネットワーク設定に自信がない方に向けて、本記事では4つのネットワークモードの違い、仕組み、使い分けをわかりやすく解説します。複雑なLinuxネットワーク名前空間の理論は省き、実務で本当に必要な知識だけをお伝えします。

まず押さえるDockerネットワークの「土台」——docker0ブリッジ

docker0とは?コンテナの「共用ゲートウェイ」

Dockerをインストールすると、システムにdocker0という仮想NICが自動的に作成されます。マンションの共用ゲートウェイのようなもので、すべてのコンテナ(住人)が外部と通信するには、ここを経由する必要があります。

ターミナルで次のコマンドを試してみましょう:

ip addr show docker0

次のような出力が表示されます:

docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

172.17.0.1がdocker0のIPアドレスです。Dockerは新しく作成するコンテナごとに、172.17.0.0/16セグメントからIPを割り当てます。例えば172.17.0.2、172.17.0.3のように。

Dockerのネットワーク一覧も確認してみましょう:

docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
7f8a2b3c9d4e   bridge    bridge    local

このデフォルトのbridgeネットワークは、下層でdocker0ブリッジを使っています。

veth pair:コンテナをつなぐ「トランシーバー」

docker0だけでは不十分です。コンテナはそれぞれ独立した「部屋」(ネットワーク名前空間)にいるのに、どうやってdocker0と通信するのでしょうか?

答えはveth pairです。一対のトランシーバーのようなもので、片方はコンテナ内のeth0、もう片方はホスト上のvethXXX(例:veth9a7b4c)として存在し、両端が直接通信します。

コンテナを起動してみましょう:

docker run -d --name test-nginx nginx

ホスト上のNICを確認します:

ip addr | grep veth

vethで始まるデバイスが増えているはずです。コンテナ内も見てみましょう:

docker exec test-nginx ip addr

コンテナ内にはeth0インターフェースがあり、IPは172.17.0.2です。このeth0とホスト上のvethXXXは一対になっており、eth0から出たパケットは瞬時にvethXXXに届き、docker0を経由して、ホストのNIC(eth0やens33など)から外部ネットワークへ出ていきます。

通信経路は次のとおりです:

コンテナ内部(172.17.0.2)
  ↓ eth0
  ↓ (veth pair)
  ↓ vethXXX

docker0ブリッジ(172.17.0.1)
  ↓ NAT転送

ホストNIC(例:192.168.1.100)

インターネット

少し回りくどく見えますが、実際の動作は非常に高速です。コンテナのIPにpingを打てば、レイテンシはだいたい0.数ミリ秒です。

正直、veth pairを初めて見たときはしばらく理解できませんでした。要するに仮想LANケーブルで、片端をコンテナ、もう片端をdocker0に差すだけ——そう考えるとシンプルです。

Bridgeモード——Dockerの「デフォルト選択」

なぜデフォルトはbridgeなのか?

ネットワークモードを指定しない場合、Dockerは自動的にbridgeモードを使います。理由はシンプルで、隔離性と使いやすさのバランスが最も良いからです。

bridgeモードでは各コンテナが独立したIPを持ち、ポート競合が起きません。同時に-pオプションでサービスをホストに簡単に公開できます。大多数のシナリオでは、これで十分です。

例えば2つのNginxコンテナを起動する場合:

docker run -d -p 8080:80 --name web1 nginx
docker run -d -p 8081:80 --name web2 nginx

両方のコンテナが80番ポートをリッスンしていても、それぞれ独立したネットワーク空間にいるため競合しません。ホストでは8080と8081でアクセスでき、裏側ではDockerがNATポート転送を行っています。

docker inspect web1でネットワーク設定を確認してみましょう:

"Networks": {
    "bridge": {
        "IPAddress": "172.17.0.2",
        "Gateway": "172.17.0.1"
    }
}

ご覧のとおり、コンテナは172.17.0.2というプライベートIPを取得し、ゲートウェイはdocker0の172.17.0.1です。

デフォルトbridge vs カスタムbridge:決定的な違い

ここに落とし穴があります。デフォルトのbridgeネットワーク(docker0)では、コンテナ間はIPアドレスでのみ通信でき、コンテナ名による名前解決はサポートされません

試してみましょう:

docker run -d --name db mysql
docker run -it --name app alpine ping db

pingは通りません。ping 172.17.0.2のようにIPを直接指定する必要があります。

一方、カスタムbridgeネットワークを作成すると:

docker network create mynet
docker run -d --name db --network mynet mysql
docker run -it --name app --network mynet alpine ping db

今度は通ります。カスタムbridgeネットワークにはDNS解決機能が組み込まれており、コンテナ名をそのままホスト名として使えます。

これが本番環境ではデフォルトdocker0ではなくカスタムネットワークを推奨する理由です。サービスディスカバリが格段に楽になり、IPを固定する必要がなくなります。

-pオプションの裏側:NAT転送

-p 8080:80を使うと、DockerはホストのiptablesにNATルールを追加します:

iptables -t nat -L -n | grep 8080

次のような出力が見えます:

DNAT  tcp  --  0.0.0.0/0  0.0.0.0/0  tcp dpt:8080 to:172.17.0.2:80

これは、ホストの8080番ポート宛てのトラフィックをすべてコンテナの172.17.0.2:80に転送する、という意味です。

外部からhttp://ホストIP:8080でコンテナ内のサービスにアクセスできるのは、Dockerがアドレス変換を代行してくれているからです。

Bridgeモードの適用シナリオ

結局、bridgeモードは次のようなシナリオに向いています:

  • マイクロサービスアーキテクチャ:複数コンテナが協調動作し、隔離しつつ相互通信が必要(カスタムbridgeネットワークを使用)
  • 開発環境:素早くサービスを立ち上げてテスト、デフォルトbridgeで十分
  • ポートマッピングが必要なWebアプリ:ブログやAPIサービスなど

性能面では、bridgeモードにはNATとveth pairのオーバーヘッドがあります。ただし正直なところ、大多数のアプリケーションではこの損失は無視できます。本当に性能のボトルネックになるケースは多くありません。最初から心配しすぎる必要はありません。

Hostモード——「性能最優先」の選択

Hostモードとは?ネットワーク隔離なしの「直結」

Hostモードは最もシンプルで大胆です。コンテナに独立したネットワークを持たせず、ホストのネットワークスタックをそのまま共有します。

起動時に--net=hostを付けます:

docker run -d --net=host --name web nginx

このときコンテナには独立したIPもeth0もありません。ホストのネットワークインターフェースを直接共有します。コンテナ内でip addrを実行すると、ホスト上の出力とまったく同じ内容が表示されます。

さらに重要なのは、-pによるポートマッピングが不要になることです。コンテナ内のサービスが80番ポートをリッスンすれば、外部からホストIP:80で直接アクセスできます。

性能上のメリットはどこにある?

Hostモードはdocker0ブリッジとveth pairをスキップし、NAT転送も不要です。パケットはホストNICから直接出入りし、ホスト上でプロセスを動かしているのとほぼ同じ状態になります。

ベンチマークによると、高並行シナリオではhostモードがbridgeモードより5〜10%ほど高速です。一見わずかに見えますが、高頻度取引やリアルタイムゲームサーバーなど、レイテンシに極端に敏感なアプリケーションでは、この差が意味を持ちます。

以前、Nginxをリバースプロキシとして使い、毎秒数万リクエストを処理する案件がありました。hostモードに切り替えたところ、P99レイテンシが12msから9msに下がりました。3ミリ秒の差ですが、そのプロジェクトにとっては相当な価値がありました。

Hostモードの落とし穴と代償

性能は上がりますが、落とし穴も少なくありません:

落とし穴1:ポート競合

ホストのポートを直接使用するため、同じポートをリッスンする複数コンテナを起動するとエラーになります:

docker run -d --net=host nginx  # 80番をリッスン
docker run -d --net=host nginx  # また80番、エラー:Address already in use

ホスト上で2つのNginxを直接起動するのと同じです。複数インスタンスを動かしたいなら、コンテナ内のリッスンポートを変えるか、hostモードを使わないでください。

落とし穴2:コンテナ内サービスは0.0.0.0をリッスンする必要がある

コンテナ内のサービスが127.0.0.1だけをリッスンしていると、外部からアクセスできません。0.0.0.0をリッスンする必要があります。

あるとき、Node.jsサービスをhostモードで起動したのに、コードがapp.listen(3000, 'localhost')になっていて、外部から接続できませんでした。app.listen(3000, '0.0.0.0')に変更して解決しました。

落とし穴3:ネットワーク隔離の喪失

コンテナからホストのすべてのネットワークリソースに直接アクセスできます。セキュリティリスクが高く、信頼できないサードパーティコードを動かす場合はhostモードは避けるべきです。

Hostモードはいつ使う?

正直なところ、本当に性能ボトルネックに直面したときだけhostモードを検討してください。大多数のシナリオでは、bridgeモードのオーバーヘッドは問題になりません。

Hostモードが向いているシナリオ:

  • 監視ツール:Prometheus、Grafana、ELKなど、ホストのネットワークリソースに直接アクセスが必要
  • 高性能プロキシ:Nginx、HAProxyによるロードバランシングで、極限のレイテンシを追求
  • データベース:MySQL、Redisなどネットワーク性能に敏感なサービス(ただしセキュリティは要評価)

アプリケーションのリクエスト量が毎秒数千以内なら、hostモードにわざわざ切り替える必要はありません。bridgeで十分です。

NoneとContainerモード——「特殊シナリオ専用」

Noneモード:完全にネットワークを切断したサンドボックス

Noneモードは文字どおり、コンテナにネットワークがありません。

docker run -it --net=none alpine sh

コンテナ内でip addrを実行すると、loopbackインターフェース(lo)しか見えません。外部ネットワークにも接続できず、他のコンテナからもアクセスできません。

Noneモードはいつ使う?

正直、実務ではnoneモードを使ったことがほとんどありません。用途は非常に限定的です:

  • セキュリティテスト:信頼できないコードを実行し、ネットワークを完全隔離してデータ漏洩を防ぐ
  • オフラインのデータ処理:コンテナはローカル計算のみ行い、ネットワーク通信が不要
  • 手動ネットワーク設定:ごく稀に、pipeworkなどのツールでvethを手動設定する必要がある場合

セキュリティ研究や特殊なネットワーク構成が必要な場合を除き、基本的に使う機会はありません。

Containerモード:2つのコンテナが「ネットワークを共有」

Containerモードは、あるコンテナが別のコンテナのネットワーク名前空間を使います。言葉だけだとわかりにくいので、例を見てみましょう:

# 最初のコンテナを起動
docker run -d --name web nginx

# 2つ目のコンテナがwebのネットワークを共有
docker run -it --net=container:web alpine sh

2つのコンテナは同じネットワーク設定を共有します。IPアドレス、ポート空間、NIC設定がすべて同一です。2つ目のコンテナ内からlocalhost:80でnginxにアクセスできます。

Containerモードの典型例:KubernetesのPod

KubernetesのPodは、実はcontainerモードで実装されています。1つのPod内に複数コンテナがあり、それらは「pause」コンテナのネットワークを共有します。

例えば、Pod内でアプリケーションコンテナとログ収集用のsidecarコンテナが動いている場合、両者はlocalhost経由で通信でき、外部にポートを公開する必要がありません。

ただし、KubernetesではなくDocker単体を使う場合、containerモードを使う機会は多くありません。bridgeモード+カスタムネットワークでもコンテナ間通信は実現でき、より柔軟です。

この2モードの位置づけ

結局、noneとcontainerは「日常の選択肢」というより「下層の能力」に近いものです。特殊シナリオ向けの柔軟性を提供しますが、80%のケースでは不要です。

覚えておくポイント:

  • Noneモード:ネットワークを完全隔離したいとき(非常に稀)
  • Containerモード:Kubernetesなどのオーケストレーションツールでよく見る。Docker単体ではあまり使わない

実践的な意思決定:適切なネットワークモードの選び方

意思決定フローチャート

具体的なプロジェクトでどのモードを選ぶべきか?シンプルな意思決定フローをまとめました:

ネットワーク隔離は必要?

├─ No → 性能ボトルネックはある?
│       │
│       ├─ Yes → Hostモード(セキュリティリスクに注意)
│       └─ No  → Bridgeモード(より安全)

└─ Yes → コンテナ名での通信が必要?

        ├─ Yes → カスタムBridgeネットワーク
        └─ No  → デフォルトBridgeネットワーク

特殊シナリオ

  • ネットワークがまったく不要 → Noneモード
  • Kubernetes Pod内のコンテナ → Containerモード

シナリオ別おすすめ早見表

シナリオ推奨モード理由
マイクロサービス(複数コンテナ協調)カスタムbridgeコンテナ名解決に対応、隔離性も良好
単一Webアプリデフォルトbridgeシンプルで十分、1コマンドで起動可能
高性能DB/キャッシュHostネットワークオーバーヘッドを削減(セキュリティ要評価)
監視ツール(Prometheus/ELK)Hostホストリソースへの直接アクセスが必要
ロードバランサー(Nginx/HAProxy)Host極限のレイテンシを追求
開発・テスト環境デフォルトbridge素早く起動、複雑な設定不要
K8s Pod内のsidecarコンテナContainerメインコンテナとネットワーク共有
セキュリティサンドボックス/オフラインタスクNoneネットワークを完全隔離

3つのよくある誤解

誤解1:「Hostモードが常に最善」

違います。Hostモードは隔離性と柔軟性を犠牲にして得る性能向上は、多くのシナリオでは無視できるレベルです。

すべてのコンテナをhostモードで動かしている人を見たことがあります。ポート競合やセキュリティ問題が山積みになり、性能は確かに少し上がりましたが、運用コストは10倍になっていました。

真実:80%のアプリケーションはbridgeモードで十分。「性能が良い」という言葉に惑わされないでください。

誤解2:「デフォルトbridgeで十分」

本番環境では推奨されません。デフォルトbridgeはコンテナ名解決をサポートしないため、複数サービス間の通信でIPを固定するか、環境変数でIPを渡す必要があり、非常に脆い構成になります。

カスタムbridgeネットワークの作成は簡単です:

docker network create mynet
# docker-compose.yml で network を指定

真実:2分かけてカスタムネットワークを設定すれば、何時間ものトラブルシュートを省けます。

誤解3:「コンテナのネットワーク問題はすべてモード選択ミス」

必ずしもそうではありません。多くの場合、ファイアウォール、iptables設定、DNSの問題です。

トラブルシュート手順:

  1. コンテナ内からゲートウェイ(docker0のIP)にpingできるか確認
  2. 次にホストの外部IPにpingできるか確認
  3. iptablesルールにDROPがないか確認
  4. Docker daemonの設定(/etc/docker/daemon.json)を確認

真実:モード選択は第一歩にすぎません。ネットワーク問題は体系的に切り分ける必要があります。

応用テクニック

テクニック1:1つのコンテナを複数ネットワークに参加させる

フロントエンドネットワークとバックエンドネットワークの両方に接続したい場合:

docker network create frontend
docker network create backend

docker run -d --name web --network frontend nginx
docker network connect backend web

webコンテナはfrontendとbackendの両方のネットワークに同時に参加します。

テクニック2:IP割り当てを精密に制御

カスタムネットワーク作成時にサブネットとゲートウェイを指定できます:

docker network create \
  --driver bridge \
  --subnet 192.168.10.0/24 \
  --gateway 192.168.10.1 \
  mynet

docker run -d --network mynet --ip 192.168.10.100 nginx

固定IPが必要なシナリオ(ファイアウォールのホワイトリストなど)で有用です。

テクニック3:ネットワーク問題の切り分けに使えるツール

コンテナ内でのネットワークトラブルシュートに便利なコマンド:

# ネットワークツールをインストール
docker exec -it <container> apk add curl netcat-openbsd

# 接続テスト
docker exec <container> nc -zv <host> <port>

# ルーティングテーブル確認
docker exec <container> ip route

# パケットキャプチャ(ホスト権限が必要)
docker exec <container> tcpdump -i eth0

まとめ

ここまで4つのネットワークモードを見てきました。要点をおさらいします:

  • Bridgeモード:デフォルト選択。大多数のシナリオに適し、本番ではカスタムbridgeネットワークを推奨
  • Hostモード:性能優先だが隔離性を犠牲にする。本当にボトルネックがあるときだけ
  • Noneモード:完全にネットワークを切断。ほとんど使わない
  • Containerモード:ネットワーク共有。主にKubernetesで使われる

覚えておいてほしいのは、「最善のモード」はなく、「最適なモード」があるということです。

Dockerを始めたばかりなら、デフォルトbridgeから始めましょう。具体的な問題が出たら調整します。サービスディスカバリが面倒ならカスタムbridgeに切り替え、性能が本当に足りなければhostを検討。最初からどのモードが「最適」か悩む必要はありません。

カスタムネットワークを作成し、いくつかコンテナを起動して、コンテナ名で相互アクセスできるか試してみてください。実際に動かす方が、10記事読むより理解が深まります。

実プロジェクトでDockerのネットワーク問題に直面したら、ぜひコメントで共有してください。この分野は奥が深いですが、ここで紹介した基本概念を押さえておけば、80%の問題は自分で解決できるはずです。

Dockerネットワークモード選択完全ガイド

bridge/host/none/containerの4モードの仕組み、性能比較、適用シナリオを深掘り解説

⏱️ 目安時間: 30 分

  1. 1

    ステップ1: 4つのネットワークモードを理解する

    4つのネットワークモード:

    bridge(デフォルト)
    • docker0ブリッジ経由で通信、ポートマッピングが必要
    • 大多数のシナリオに適し、hostより性能はやや劣るがセキュリティは高い

    hostモード
    • ホストのネットワークを直接使用、ポートマッピング不要
    • 性能最高(ネイティブに近い)だがセキュリティは低い(コンテナがホストネットワークに直接露出)
    • 高性能シナリオ向け

    noneモード
    • ネットワークなし、完全隔離

    containerモード
    • 他コンテナのネットワーク名前空間を共有
  2. 2

    ステップ2: 性能比較とシナリオ選択

    性能比較:
    • hostモードが最高(ネイティブに近い)
    • bridgeモードはやや劣る(NATオーバーヘッドあり)
    • containerモードは共有先コンテナ次第
    • noneモードはネットワークなし

    シナリオ選択:
    • 大多数のケースはbridgeモード(デフォルト、安全、ポートマッピング必要)
    • 高性能要件はhostモード(性能最高だがセキュリティ低)
    • 完全隔離はnoneモード(ネットワークなし、完全隔離)
    • コンテナ間でネットワーク共有はcontainerモード(他コンテナのネットワーク名前空間を共有)
  3. 3

    ステップ3: 実践設定とベストプラクティス

    bridgeモードの設定:
    • docker run -d -p 8080:80 nginx(デフォルトbridge、ポートマッピング)
    • カスタムネットワーク作成:docker network create my-network
    • カスタムネットワーク使用:docker run --network my-network

    hostモードの設定:
    • docker run --network host nginx(ホストネットワークを直接使用)

    ベストプラクティス:
    • Dockerを始めたばかりなら、デフォルトbridgeから始めれば十分
    • 具体的な問題が出たら調整する
    • サービスディスカバリが面倒ならカスタムbridgeに切り替える
    • 性能が本当に足りなければhostを検討
    • 最初からどのモードが「最適」か悩まない

FAQ

Dockerには4つのネットワークモードがある?それぞれの特徴は?
4つのネットワークモード:

bridge(デフォルト):
• docker0ブリッジ経由で通信、ポートマッピングが必要
• 大多数のシナリオに適し、hostより性能はやや劣るがセキュリティは高い

hostモード:
• ホストのネットワークを直接使用、ポートマッピング不要
• 性能最高(ネイティブに近い)だがセキュリティは低い(コンテナがホストネットワークに直接露出)
• 高性能シナリオ向け

noneモード:
• ネットワークなし、完全隔離

containerモード:
• 他コンテナのネットワーク名前空間を共有
bridgeモードとhostモードの違いは?
bridgeモード:
• デフォルトモード、コンテナはdocker0ブリッジ経由で通信
• -pオプションでポートマッピングが必要
• 大多数のシナリオに適し、hostより性能はやや劣るがセキュリティは高い

hostモード:
• ホストのネットワークを直接使用、ポートマッピング不要
• 性能最高(ネイティブに近い)
• ただしセキュリティは低い(コンテナがホストネットワークに直接露出)
• 高性能シナリオ向け

性能比較:hostモードが最高(ネイティブに近い)、bridgeモードはやや劣る(NATオーバーヘッドあり)。
適切なネットワークモードの選び方は?
シナリオ選択:
• 大多数のケースはbridgeモード(デフォルト、安全、ポートマッピング必要)
• 高性能要件はhostモード(性能最高だがセキュリティ低)
• 完全隔離はnoneモード(ネットワークなし、完全隔離)
• コンテナ間でネットワーク共有はcontainerモード(他コンテナのネットワーク名前空間を共有)

ベストプラクティス:
• Dockerを始めたばかりなら、デフォルトbridgeから始めれば十分
• 具体的な問題が出たら調整する
• サービスディスカバリが面倒ならカスタムbridgeに切り替える
• 性能が本当に足りなければhostを検討
• 最初からどのモードが「最適」か悩まない

5分で読めます · 公開日: 2025年12月17日 · 更新日: 2026年6月8日

関連記事

コメント

GitHubアカウントでログインしてコメントできます