#コンテナネットワークについて
Dockerにおいてデフォルトで存在するネットワークは以下の3つがあります。
###bridge
bridgeはDockerが提供するNAT用のネットワークです。基本的にはbridgeが最もコンテナの利点を活用できます。
Dockerをインストールしたホスト環境には、docker0
というデフォルトbridgeネットワーク
が作成されます。
このデフォルトのbridgeはコンテナ名ベースの名前解決機能を持っていません。
反対にユーザ自身が新たに作成したbridge(ユーザ定義bridgeネットワーク
)はこのコンテナ名ベースの名前解決機能を持っています。
詳細は後ほど記載します。
###host
hostはDockerホストのネットワークをそのまま利用するため、ホストのインターフェースと同じIPアドレスでhostネットワークに属するコンテナにアクセスすることができます。(利用するポートもホストと共有されるため、ホストでポート80を使っていればコンテナはポート80を使えません)
###none
noneネットワークに属したコンテナはネットワークインターフェースを持たないため、インターネットや他のコンテナとも通信ができません。
(参照先: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)
ホスト環境の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は、異なるネットワークネームスペースに割り当てられていないと通信ができません。(※)
なぜ、このようなペアで作られるのでしょうか。それはコンテナにおけるネットワークネームスペースの仕組みにあります。
(参照: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