LoginSignup
7
6

More than 1 year has passed since last update.

【Docker】コンテナネットワークの基礎知識(bridgeネットワークについて)

Last updated at Posted at 2021-11-12

コンテナネットワークについて

Dockerにおいてデフォルトで存在するネットワークは以下の3つがあります。

bridge

bridgeはDockerが提供するNAT用のネットワークです。基本的にはbridgeが最もコンテナの利点を活用できます。
Dockerをインストールしたホスト環境には、docker0というデフォルトbridgeネットワークが作成されます。
このデフォルトのbridgeはコンテナ名ベースの名前解決機能を持っていません。
反対にユーザ自身が新たに作成したbridge(ユーザ定義bridgeネットワーク)はこのコンテナ名ベースの名前解決機能を持っています。
詳細は後ほど記載します。

host

hostはDockerホストのネットワークをそのまま利用するため、ホストのインターフェースと同じIPアドレスでhostネットワークに属するコンテナにアクセスすることができます。(利用するポートもホストと共有されるため、ホストでポート80を使っていればコンテナはポート80を使えません)

none

noneネットワークに属したコンテナはネットワークインターフェースを持たないため、インターネットや他のコンテナとも通信ができません。

image.png
(参照先:https://knowledge.sakura.ad.jp/23899/)

bridgeネットワーク

ここでは、デフォルトのbridgeネットワーク(docker0)を例にbridgeネットワークについて説明します。

デフォルトbridgeネットワーク

docker network inspect bridgeでデフォルトのブリッジネットワーク(docker0)について確認できます。

$ docker network inspect bridge
[
   {
       "Name": "bridge",
       "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
       "Scope": "local",
       "Driver": "bridge",
       "IPAM": {
           "Driver": "default",
           "Config": [
               {
                   "Subnet": "172.17.0.1/16",
                   "Gateway": "172.17.0.1"
               }
           ]
       },
       "Containers": {},
       "Options": {
           "com.docker.network.bridge.default_bridge": "true",
           "com.docker.network.bridge.enable_icc": "true",
           "com.docker.network.bridge.enable_ip_masquerade": "true",
           "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
           "com.docker.network.bridge.name": "docker0",
           "com.docker.network.driver.mtu": "9001"
       }
   }
]

デフォルトのbridgeネットワークであるdocker0では、以下のようなコンテナアクセスを実現します。
(参照先:https://christina04.hatenablog.com/entry/2016/07/22/193000)
image.png

ホスト環境のNICに対して、eth0というネットワークインターフェースが割り当てられ、
このeth0にdocker0(デフォルトのbridgeネットワーク)が接続されています。
ホストOSが提供するiptablesにより、外部ネットワークとdocker0のネットワークアドレス変換(NAT:Network Address Translation)が行われ、コンテナは外部ネットワークと通信できます。

上の図のContainer1とContainer2は、それぞれの同一ネットワーク内の通信となるため、双方のコンテナ間ではL2通信(ARPによるアドレス解決)が行われます。(厳密にはそれぞれのコンテナのethのペアであるveth間でL2通信が行われる。それより先は各vethに接続されたコンテナに中継される。)

また、内部にあるコンテナからインターネットなどの外部ネットワークへの通信においては、
NAPT(IPマスカレード)を使ってグローバルIPアドレスに変換して通信を行います。
そして返りの通信でもNAPT(IPマスカレード)を使って、元のプライベートIPアドレスに変換されて送信元のコンテナへ送られます。

もちろん、NAPT(IPマスカレード)ではポートフォワーディングも行います。
(Dockerコンテナにおけるポートフォワーディングについては、以前の記事を参照してください。)

docker0

DockerをインストールしたLinuxホストには、docker0という仮想ブリッジがデフォルトで作成されます。
仮想ブリッジとは、Linux上に構成されている仮想的なL2スイッチのことです。
このブリッジに到達したパケットは、宛先情報を確認され、宛先のコンテナや外部へ中継されます。

veth(virtual eth)

vethとは、仮想NICのことです。ただ、コンテナネットワークにおいては2つのveth(仮想NIC)のペアによって通信が行われます。
この2つのveth間で通信を行うことができ、1つはホスト側のネットワークネームスペースに割り当てられ、もう1つはコンテナ側のネットワークネームスペースに割り当てられます。(下図のような感じ)
ホスト側のネットワークネームスペースに割り当てられたvethは、ホスト上にあるブリッジ(docker0)に接続すると、ブリッジを介してホスト外との通信が可能となります。
この2つのvethは、異なるネットワークネームスペースに割り当てられていないと通信ができません。(※)
なぜ、このようなペアで作られるのでしょうか。それはコンテナにおけるネットワークネームスペースの仕組みにあります。
image.png
(参照:https://gihyo.jp/admin/serial/01/linux_containers/0006)

コンテナにおけるネットワークネームスペース

ネットワークネームスペースにおいては、ネットワークリソース(IPアドレスやRTテーブル、ポート番号など)をネームスペースという区切られた空間ごとに独立して持つことができます。(上図の青色の部分と、黄色の部分)
これにより、コンテナ側はホスト環境とは別のネットワークとして扱われるため、ホスト側とIPアドレスやポートが重複しても問題なく通信が可能となります。
つまり、ホスト上のインターフェースにそのままコンテナが割り当てられている場合(これがhostネットワーク)、ホスト環境とIPアドレスやポート番号が共有されてしまいます。

ユーザ定義ブリッジネットワーク

デフォルトのbridgeネットワークとは別に、自分で作成するユーザ定義bridgeネットワークがあり、この2つは名前解決機能において差があります。

コンテナネットワークにおける名前解決は、普通の名前解決の仕組みと比べて少し特殊です。
複数のコンテナを連携させるためには、コンテナ名ベースで名前解決を実現するのが一般的です。コンテナは使い捨てする運用が多いため、IPアドレスが頻繁に変わります。そのため、コンテナ名ベースで名前解決を行ったほうが都合が良いのです。
コンテナ名ベースで名前解決を行う場合は、デフォルトのbridgeネットワーク(docker0)を使うのではなく、自身で新たに作成したbridgeネットワーク(ユーザ定義bridgeネットワーク)を使うのが一般的です。
ユーザ定義されたbridgeネットワークは、デフォルトのbridgeネットワークと異なり、コンテナ名ベースでの名前解決が可能となります。(コンテナ名を指定してping疎通を行うことができる)

docker network createコマンドで、-dオプションでbridgeを指定すれば新しいbridgeネットワークを作成できます。
ここではbridge1という新しいbridgeネットワークを新規作成します。

$ docker network create -d bridge bridge1
daa4195aab0bd7da4f20371d15660529a016457aee8eaef936f028f62c18229f

docker network lsコマンドで新しく作成されていることを確認します。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1916875b8e0e        bridge              bridge              local
9d80476b295c        host                host                local
daa4195aab0b        bridge1             bridge              local
f1b79f29f8a4        none                null                local

新しいbridgeネットワーク上でコンテナを起動するときは、docker container runコマンドの--networkオプションでネットワークを指定して起動できます。

$ docker container run --rm -d --name ct1 --network bridge1 ubuntu:16.04 
398a562546a16530a9569b9a54734c3be3ce5676286935105745c66021d1bb45

参考サイト

https://knowledge.sakura.ad.jp/23899/
https://gihyo.jp/admin/serial/01/linux_containers/0006

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6