Posted at

Docker の基本学習 ~ Docker のネットワーク

More than 3 years have passed since last update.

単一ホスト内での Docker のネットワークの仕組みをまとめてみる。


全体像

まず、Docker のネットワークは以下の図ような構成になっている。

ざっとポイントをまとめるとこんな感じ。

* ホストには docker0 という仮想ブリッジが作成される

* コンテナは veth を介して仮想ブリッジに接続される

* コンテナ内からは eth0 というNIC があるように見える(実体は veth)

* コンテナ内の eth0 には、空いているIPアドレスが自動で割り当てられる(なので、IPアドレスは不定)。

* コンテナからホストの外部に通信するには、NAT(IPマスカレード)が使われる

* 単一ホスト上のコンテナ間の通信は、仮想ブリッジを経由して行われる(なので、コンテナ内で見える 172.17.0.0/16 のアドレスを使って通信できる)


もう少し詳しく

分からないところを調べてみた。


仮想ブリッジ

Linux 上に仮想的なL2スイッチを構成する機能(VMware ESXi でいえば、仮想スイッチのことかな)。Docker をインストールしたLinuxホストでは docker0 という仮想ブリッジが作られる。

# インターフェイスの表示

$ ifconfig -a
docker0 Link encap:Ethernet HWaddr 56:84:7A:FE:97:99
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0
(略...)

eth0 Link encap:Ethernet HWaddr 06:D8:0E:5D:B8:C9
inet addr:10.0.0.73 Bcast:10.0.0.255 Mask:255.255.255.0
(略...)

# 仮想ブリッジの情報を表示してみる。
$ sudo yum install bridge-utils
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.56847afe9799 no


veth

veth とは、仮想的なネットワークインターフェース(仮想NIC)。ただ、単純な仮想NICではなく、veth を作成すると2つの仮想NICのペアができ、この2つの間で通信ができるようになる(2つのNICをクロスケーブルで直結して通信する感じ)。

2つの veth のうち、1つはコンテナのネットワーク名前空間に入れられて、コンテナ内からのみ見えるようになる。また、名前も、コンテナ内では veth から eth0 に変更されている。

もう1つの veth は、ホスト側の仮想ブリッジ(docker0)に接続される。

コンテナを起動した後、ホストからは以下のように veth が作られていることが見れる。

$ ifconfig -a

docker0 Link encap:Ethernet HWaddr 56:84:7A:FE:97:99
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0
(略...)

eth0 Link encap:Ethernet HWaddr 06:D8:0E:5D:B8:C9
inet addr:10.0.0.73 Bcast:10.0.0.255 Mask:255.255.255.0
(略...)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
(略...)

# コンテナを起動したら作成された(ホスト側の veth)
vethbe8a6db Link encap:Ethernet HWaddr E6:B0:26:46:48:C6
inet6 addr: fe80::e4b0:26ff:fe46:48c6/64 Scope:Link
UP BROADCAST RUNNING MTU:9001 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:508 (508.0 b) TX bytes:438 (438.0 b)

# たぶん、ホスト側の veth が仮想ブリッジ(docker0)に接続されていることを表している
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.56847afe9799 no vethbe8a6db

また、コンテナ内からは eth0 が見える。そして、Default Gateway(DGW) は、ホスト側の docker0 の IPアドレスになっており、この DGW を経由して NAT で外部と通信することになる。

# ifconfig -a

eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
(略...)

# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 172.17.42.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 * 255.255.0.0 U 0 0 0 eth0


コンテナへのIPアドレスの割り当て

コンテナには、Docker が管理しているアドレス空間から空いている(使われていない)IPアドレスが自動で割り当てられる。なので、コンテナ内のIPは不定となる。

そのため、同一ホスト上に2つのコンテナがあるとして、一方から他方に通信したい場合は、リンクの機能 を使って接続先のIPアドレスを取得し、接続するという方法を取ることになる。


参考サイト

KVMで始めるプライベート・クラウドへの第一歩

第6回 Linuxカーネルのコンテナ機能[5] ─ネットワーク

Docker入門: コンテナ型仮想化技術の仕組みと使い方