Dockerを活用するためのネットワーク関連操作のおさらい


# 概要
Dockerコンテナを操作するときに「上手く繋がらない」となることがよくあります。その理由にネットワーク構成を把握できていないことが少なからずあったりました。そこで、Dockerの基本的なネットワーク構成を整理するとともに、ネットワーク操作の基本コマンドを再整理してみます。



# DockerクライアントとDockerホスト(Dockerエンジン)の構成パターン

まず、[Dockerのドキュメント](https://docs.docker.com)にあるキーコンセプトを押さえておきます。



## DockerクライアントをDockerホスト上で使うケース
DockerクライアントとDockerホストが同一マシンにある場合です。シンプルな構成。これが基本です。
![スクリーンショット 2015-12-06 20.24.30.png](https://qiita-image-store.s3.amazonaws.com/0/79341/972c7ca5-6e86-0a59-ea80-5f338e729f48.png "スクリーンショット 2015-12-06 20.24.30.png")



## DockerクライアントをDockerホストとは別の環境で使うケース
これは、OS-XやWindowsでDocker環境を構築したときの構成です。仮想環境が一枚噛みます。OS-XやWindowsがホストOSでLinuxがゲストOSです。
![スクリーンショット 2015-12-06 20.25.33.png](https://qiita-image-store.s3.amazonaws.com/0/79341/d7b9d110-e519-b93e-7573-5ba3df5bddc5.png "スクリーンショット 2015-12-06 20.25.33.png")



# Dockerのネットワーク構成

__DockerクライアントをDockerホストとは別の環境で使うケース__で考えます。

Windows上にVirtualBoxを導入して、VirtualBoxでDockerホストを構築して、その上にDockerコンテナを構築したときのネットワークを考えます。※環境や起動順によってIPアドレスは変わります。

Dockerを含んだ全体のネットワーク構成はこんな感じになります。
![スクリーンショット 2015-12-06 20.34.25.png](https://qiita-image-store.s3.amazonaws.com/0/79341/df1fc85f-543c-7228-3a3a-d8214eca14ed.png "スクリーンショット 2015-12-06 20.34.25.png")


## Windowsマシン(リアル、ホストOS)
- IP(デフォルト) : 192.168.1.140/24
- IP(#3) : 192.168.99.1/24

`ipconfig`でIPアドレスを確認します（関係あるものだけ抜粋します）。

```
C:¥>ipconfig

Windows IP 構成

イーサネット アダプター イーサネット:

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80::1dbd:631d:c6b4:9334%4
   IPv4 アドレス . . . . . . . . . . . .: 192.168.1.140
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .: 192.168.1.1

・・・

イーサネット アダプター イーサネット 3:

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: fe80::cd1:6968:d2a2:148c%21
   IPv4 アドレス . . . . . . . . . . . .: 192.168.99.1
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .:
・・・
```

`route`でルーティングテーブルを確認します（関係のあるもののみ示します）。

```
C:¥>route print -4
・・・
IPv4 ルート テーブル
===========================================================================
アクティブ ルート:
ネットワーク宛先        ネットマスク          ゲートウェイ       インターフェイ
ス  メトリック
          0.0.0.0          0.0.0.0      192.168.1.1    192.168.1.140    266
        127.0.0.0        255.0.0.0            リンク上         127.0.0.1    306
        127.0.0.1  255.255.255.255            リンク上         127.0.0.1    306
  127.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
      192.168.1.0    255.255.255.0            リンク上     192.168.1.140    266
    192.168.1.140  255.255.255.255            リンク上     192.168.1.140    266
    192.168.1.255  255.255.255.255            リンク上     192.168.1.140    266
     192.168.56.0    255.255.255.0            リンク上      192.168.56.1    276
     192.168.56.1  255.255.255.255            リンク上      192.168.56.1    276
   192.168.56.255  255.255.255.255            リンク上      192.168.56.1    276
     192.168.99.0    255.255.255.0            リンク上      192.168.99.1    276
     192.168.99.1  255.255.255.255            リンク上      192.168.99.1    276
   192.168.99.255  255.255.255.255            リンク上      192.168.99.1    276
        224.0.0.0        240.0.0.0            リンク上         127.0.0.1    306
        224.0.0.0        240.0.0.0            リンク上     192.168.1.140    266
        224.0.0.0        240.0.0.0            リンク上      192.168.56.1    276
        224.0.0.0        240.0.0.0            リンク上      192.168.99.1    276
  255.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
  255.255.255.255  255.255.255.255            リンク上     192.168.1.140    266
  255.255.255.255  255.255.255.255            リンク上      192.168.56.1    276
  255.255.255.255  255.255.255.255            リンク上      192.168.99.1    276
===========================================================================
・・・
```




## Dokckerホスト(on VirtualBox、ゲストOS)
- IP(eth0) : 10.0.2.15/24
- IP(eth1) : 192.168.99.101/24
- IP(docker0) : 172.17.0.1/16

`docker-machine`を使ってDockerホストへログインします。

```
$ docker-machine ssh default
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
_                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.9.1, build master : cef800b - Fri Nov 20 19:33:59 UTC 2015
Docker version 1.9.1, build a34a1d5
```

`ifconfig`でIPアドレスを調べます（関係のあるものだけを示します。）

```
docker@default:~$ ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:89:A5:A7:2A
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:89ff:fea5:a72a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:32957 errors:0 dropped:0 overruns:0 frame:0
          TX packets:32030 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:14255638 (13.5 MiB)  TX bytes:59417320 (56.6 MiB)

eth0      Link encap:Ethernet  HWaddr 08:00:27:1A:FC:A8
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe1a:fca8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1087659 errors:0 dropped:0 overruns:0 frame:0
          TX packets:174594 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1551817845 (1.4 GiB)  TX bytes:13156215 (12.5 MiB)

eth1      Link encap:Ethernet  HWaddr 08:00:27:D1:D3:B2
          inet addr:192.168.99.101  Bcast:192.168.99.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fed1:d3b2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:30681 errors:0 dropped:0 overruns:0 frame:0
          TX packets:45195 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:5212686 (4.9 MiB)  TX bytes:27678816 (26.3 MiB)
```

`route`でルーティングテーブルを確認します。

```
docker@default:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.2.2        0.0.0.0         UG    1      0        0 eth0
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
127.0.0.1       0.0.0.0         255.255.255.255 UH    0      0        0 lo
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.99.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1
```




## Dockerコンテナ(on Dockerホスト)

|Dockerコンテナ  |IP            |
|:------------:|:------------:|
|Jenkins       |172.17.0.3/16 |
|mysql         |172.17.0.4/16 |
|sonarqube     |172.17.0.6/16 |
|selenium-hub  |172.17.0.2/16 |
|chrome        |172.17.0.5/16 |
|firefox       |172.17.0.7/16 |
|glassfish     |172.17.0.8/16 |


Dockerコンテナに対してはWindows上のDockerクライアントを使います。

まず、`docker-compose ps`でDockerコンテナをリストアップします。

```
$ docker-compose ps
        Name                       Command               State                                      Ports
-------------------------------------------------------------------------------------------------------------------------------------------
work_chrome_1           /opt/bin/entry_point.sh          Up       0.0.0.0:5900->5900/tcp
work_firefox_1          /opt/bin/entry_point.sh          Up       0.0.0.0:5901->5900/tcp
work_glassfish_1        /bin/sh -c asadmin start-d ...   Up       0.0.0.0:14848->4848/tcp, 0.0.0.0:18080->8080/tcp, 0.0.0.0:18181->8181/tcp
work_jenkins_1          /bin/tini -- /usr/local/bi ...   Up       50000/tcp, 0.0.0.0:8080->8080/tcp
work_jenkins_data_1     /bin/tini -- /usr/local/bi ...   Exit 0
work_mysql_1            /entrypoint.sh mysqld            Up       0.0.0.0:3306->3306/tcp
work_mysql_data_1       /entrypoint.sh echo sonarq ...   Exit 0
work_selenium-hub_1     /opt/bin/entry_point.sh          Up       0.0.0.0:4444->4444/tcp
work_sonarqube_1        ./bin/run.sh                     Up       0.0.0.0:9000->9000/tcp
work_sonarqube_data_1   ./bin/run.sh echo sonarqub ...   Exit 0
```

それぞれのDockerコンテナに対して`docker inspect`します。

```
$ docker inspect -f "{{ .NetworkSettings.Networks.bridge.IPAddress }}" work_jennkins_1
172.17.0.3
```


# DockerコンテナのサービスをホストOS以外のマシンに提供する
ポートフォワードを使って実現します。

```
Windowsのポート -> Dockerホストのポート -> Dockerコンテナのポート
```

Dockerホストのポート -> Dockerコンテナのポート は、`docker-compose ps`のPorts欄で確認できます。

Windowsのポート -> Dockerホストのポート は、次にVirtualBoxのネットワーク設定で確認できます。

![スクリーンショット 2015-12-06 21.02.19.png](https://qiita-image-store.s3.amazonaws.com/0/79341/50478b51-43a8-d38b-20a0-feeeb3d54a64.png "スクリーンショット 2015-12-06 21.02.19.png")

なお、特権ポート(1024番以内)は管理者アカウントなどでないと指定できません。VirtualBoxでは指定できてしまいますが、有効な設定にはならないので注意が必要です。


# Dockerコンテナ同士を連携させる
`docker run`コマンドの__--link__でDockerコンテナを指定して連携できます。

__work__という名前のDockerコンテナを動かします。

```
$ docker run --name work --rm -it centos:6.7 bash
[root@682966ec968b /]# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:04
          inet addr:172.17.0.4  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1296 (1.2 KiB)  TX bytes:648 (648.0 b)
```

Dockerコンテナworkに別名__hoge__をつけて、別のDockerコンテナを動かします。`/etc/hosts`を見ると、workコンテナのIPアドレスが記録されています。


```
$ docker run --link work:hoge --rm -it centos bash
[root@faf60d77a2ad /]# cat /etc/hosts
172.17.0.6	faf60d77a2ad
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.4	hoge 682966ec968b work
root@faf60d77a2ad /]# ping hoge
PING hoge (172.17.0.4) 56(84) bytes of data.
64 bytes from hoge (172.17.0.4): icmp_seq=1 ttl=64 time=0.074 ms
64 bytes from hoge (172.17.0.4): icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from hoge (172.17.0.4): icmp_seq=3 ttl=64 time=0.086 ms
^C
--- hoge ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.050/0.070/0.086/0.015 ms
```






# ネットワーク操作コマンド
よく使うものをメモっておきます。

##### IPアドレスを調べる
Windowsは`ipconfig`、Dockerホストのベースであるboot2dockeryやOS-Xは`ifocnfig`、CentOS7系は`ip addr`です。

dockerコンテナを起動して確認してみます。

centos(6.7)のコンテナを起動してIPアドレスを確認します。

```
$ docker run --rm -it centos:6.7 bash
[root@a2429a14b5d2 /]# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:06
          inet addr:172.17.0.6  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:508 (508.0 b)  TX bytes:508 (508.0 b)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
```


centos(最新の7系)のコンテナを起動してIPアドレスを確認します。

```
$ docker run --rm -it centos bash
[root@aed810f13910 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.4/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:4/64 scope link
       valid_lft forever preferred_lft forever
```


##### ルーティングテーブルを調べる
Windowsは`route print -4`として、IPv4のルートテーブルを確認できます。

```
C:¥>route print -4

IPv4 ルート テーブル
===========================================================================
アクティブ ルート:
ネットワーク宛先        ネットマスク          ゲートウェイ       インターフェイ
ス  メトリック
          0.0.0.0          0.0.0.0      192.168.1.1    192.168.1.140    266
        127.0.0.0        255.0.0.0            リンク上         127.0.0.1    306
        127.0.0.1  255.255.255.255            リンク上         127.0.0.1    306
  127.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
      192.168.1.0    255.255.255.0            リンク上     192.168.1.140    266
    192.168.1.140  255.255.255.255            リンク上     192.168.1.140    266
    192.168.1.255  255.255.255.255            リンク上     192.168.1.140    266
     192.168.56.0    255.255.255.0            リンク上      192.168.56.1    276
     192.168.56.1  255.255.255.255            リンク上      192.168.56.1    276
   192.168.56.255  255.255.255.255            リンク上      192.168.56.1    276
     192.168.99.0    255.255.255.0            リンク上      192.168.99.1    276
     192.168.99.1  255.255.255.255            リンク上      192.168.99.1    276
   192.168.99.255  255.255.255.255            リンク上      192.168.99.1    276
        224.0.0.0        240.0.0.0            リンク上         127.0.0.1    306
        224.0.0.0        240.0.0.0            リンク上     192.168.1.140    266
        224.0.0.0        240.0.0.0            リンク上      192.168.56.1    276
        224.0.0.0        240.0.0.0            リンク上      192.168.99.1    276
  255.255.255.255  255.255.255.255            リンク上         127.0.0.1    306
  255.255.255.255  255.255.255.255            リンク上     192.168.1.140    266
  255.255.255.255  255.255.255.255            リンク上      192.168.56.1    276
  255.255.255.255  255.255.255.255            リンク上      192.168.99.1    276
===========================================================================
```

centos(6系)では、`route -n`で確認できます。

```
[root@a2429a14b5d2 /]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

```

`netstat -nr`でも確認できます。OS-Xでも使えます。

```
[root@a2429a14b5d2 /]# netstat -nr
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG        0 0          0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0
```

centos(7系)では、`ip route`で確認できます。

```
[root@aed810f13910 /]# ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.4
```


参考:https://thinkit.co.jp/story/2014/12/25/5412?page=0%2C2


##### ネットワークが繋がってるかを調べる
`ping`で確認できます。宛先ホストにICMP echoパケットを送り、ICMP echo replyパケットを受け取ることで、ネットワークの問題を検出します。

```
[root@aed810f13910 /]# ping google.com
PING google.com (210.139.253.104) 56(84) bytes of data.
64 bytes from cache.google.com (210.139.253.104): icmp_seq=1 ttl=61 time=5.59 ms
64 bytes from cache.google.com (210.139.253.104): icmp_seq=2 ttl=61 time=6.36 ms
^C
--- google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 5.591/5.980/6.369/0.389 ms
```


# 最後に
基本的なネットワーク構成を押さえておけばDockerコンテナをうまく使える気がします。分散環境で使ったりといったときにもきっと役たつはず。



# 参考
* [Learn the key concepts before installing](https://docs.docker.com/engine/installation/mac/)
* https://thinkit.co.jp/story/2014/12/25/5412?page=0%2C2
* [Docker Compose 1.5 について](https://www.supinf.co.jp/tech/2015/11/05/docker-compose-15/)