概要
- Dockerのネットワークまわりについて調べる
- Dockerのブリッジネットワークでどのように通信が行われるのか調べる
- リンク機能については触れない
Dockerコンテナ・ネットワーク
まず、Dockerをインストールすると、デフォルトで3つのネットワークが作成され(ここでいう「ネットワーク」は、Docker内部の概念)、docker run
したときのデフォルトは、docker0というブリッジネットワークが使われる。
# デフォルトで作成される3つのネットワーク
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
d4d0e07e3979 bridge bridge local
ba38d64470bd host host local
d1f35877f0fd none null local
# ネットワークの詳細を確認
$ docker network inspect bridge
…出力は省略
docker0はifconfigで確認ができる。
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:82ff:feeb:c7b5 prefixlen 64 scopeid 0x20<link>
ether 02:42:82:eb:c7:b5 txqueuelen 0 (イーサネット)
RX packets 7519 bytes 409824 (409.8 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 16155 bytes 18364515 (18.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
同じブリッジネットワークに属するコンテナ同士はそれぞれ通信可能なため、セキュリティ的に問題がある場合は新しくネットワークを作成し、所属するネットワークを分ける。
このブリッジはbrctlコマンドでも確認が可能であり、Linuxの標準機能で実現されていることがわかる。
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024282ebc7b5 no
起動したコンテナがこのネットワークに属していることを確認するには、docker network inspect bridge
もしくはbrctl show
を実行する。
コンテナ起動時に作成されるリソース、設定
構成
コンテナを起動すると下記のようなネットワーク構成が作られる。コンテナと外部の通信はvethによって実現され、仮想ブリッジから外へはiptablesの力を借りる。
引用元:https://www.kaitoy.xyz/2015/07/25/how-to-capture-packets-on-a-local-network-with-pcap4j-container/
veth
Linuxが提供する機能。コンテナごとに仮想NICのペアを作成し、一つはコンテナ内部に入れ(LinuxのNetwork namespaceを使う)、もう一つは仮想ブリッジと接続する。
コンテナ内部の仮想NICはeth0として作成され、ブリッジと同じサブネットのIPアドレスが自動的に割り振られる。仮想ブリッジと接続される仮想NICは、ホストOSからifconfigにより確認できる。
veth6f26945: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::fc41:30ff:fe01:3c56 prefixlen 64 scopeid 0x20<link>
ether fe:41:30:01:3c:56 txqueuelen 0 (イーサネット)
RX packets 6 bytes 516 (516.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 31 bytes 3191 (3.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
iptables
外部ネットワークとコンテナとの通信は、iptablesによりIPマスカレードにより実現する。
dockerにより追加された設定を確認する。iptables-save
で見てもいいが、ここではiptables -L
で見ている。
natテーブル
「MASQUERADE」の行がポイント。
# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
filterテーブル
特に面白い設定はないが、filterテーブルにも設定は入る。
# iptables -t filter -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-ISOLATION all -- 0.0.0.0/0 0.0.0.0/0
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
Chain DOCKER-ISOLATION (1 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
ブリッジネットワーク追加時
次のようにブリッジネットワークを追加可能。
$ docker network create --driver bridge my_bridge_nw
このときiptablesの設定も追加される。
参考
-
Docker コンテナ・ネットワークの理解
-
Dockerを支える技術
-
LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術、第6回 Linuxカーネルのコンテナ機能[5] ─ネットワーク