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

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

# 全体像
まず、Docker のネットワークは以下の図ような構成になっている。
![DockerNetwork.png](https://qiita-image-store.s3.amazonaws.com/0/79316/524c68aa-0a6b-dfdd-11d1-a4b3ce0f90ce.png)

ざっとポイントをまとめるとこんな感じ。
* ホストには docker0 という仮想ブリッジが作成される
* コンテナは veth を介して仮想ブリッジに接続される
* コンテナ内からは eth0 というNIC があるように見える(実体は veth)
* コンテナ内の eth0 には、空いているIPアドレスが自動で割り当てられる(なので、IPアドレスは不定)。
* コンテナからホストの外部に通信するには、NAT(IPマスカレード)が使われる
* 単一ホスト上のコンテナ間の通信は、仮想ブリッジを経由して行われる(なので、コンテナ内で見える 172.17.0.0/16 のアドレスを使って通信できる)

# もう少し詳しく
分からないところを調べてみた。

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

```bash
# インターフェイスの表示
$ 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 を作成すると２つの仮想NICのペアができ、この２つの間で通信ができるようになる(２つのNICをクロスケーブルで直結して通信する感じ)。

２つの veth のうち、１つはコンテナのネットワーク名前空間に入れられて、コンテナ内からのみ見えるようになる。また、名前も、コンテナ内では veth から eth0 に変更されている。
もう１つの 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つのコンテナがあるとして、一方から他方に通信したい場合は、[リンクの機能](http://qiita.com/arturias/items/75828479c1f9eb8d43fa) を使って接続先のIPアドレスを取得し、接続するという方法を取ることになる。

# 参考サイト
[KVMで始めるプライベート・クラウドへの第一歩](http://gihyo.jp/admin/serial/01/ibm_kvm/0003)
[第6回　Linuxカーネルのコンテナ機能［5］ ─ネットワーク](http://gihyo.jp/admin/serial/01/linux_containers/0006)
[Docker入門: コンテナ型仮想化技術の仕組みと使い方](http://www.slideshare.net/yuichi110/docker-introduction-42455180)