Dockerとネットワークネームスペースの関係

# Dockerとネットワークネームスペースの関係
前回はDockerCEのインストールを行いました。
https://qiita.com/sugimount/items/0b14b8d544ab1d95e219

今回は、Dockerとネットワークネームスペースの関係を見ていきます。


## コンテナ実行前の各種状態を確認
Dockerに関係している関連技術について、コンテナ実行前のタイミングで各種状態を確認していきます。  

DockerImageの現在のものを一覧

```
[root@sugi-docker-registory ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              f2a91732366c        3 months ago        1.85kB
```

LinuxBridgeの確認  
Defaultで作成されている docker0 という名前のブリッジには、何もinterfaceが接続されていません

```
[root@sugi-docker-registory ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242ac6ec522       no       
```

ipコマンドでインターフェースを確認  

```
[root@sugi-docker-registory ~]# ip -d a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0
    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
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:50:56:98:57:73 brd ff:ff:ff:ff:ff:ff promiscuity 0
    inet 192.168.120.210/24 brd 192.168.120.255 scope global ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::98a0:413d:6b71:8fbd/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:ac:6e:c5:22 brd ff:ff:ff:ff:ff:ff promiscuity 0
    bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time 30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q bridge_id 8000.2:42:ac:6e:c5:22 designated_root 8000.2:42:ac:6e:c5:22 root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0 hello_timer    0.00 tcn_timer    0.00 topology_change_timer    0.00 gc_timer    0.28 vlan_default_pvid 1 group_fwd_mask 0 group_address 01:80:c2:00:00:00 mcast_snooping 1 mcast_router 1 mcast_query_use_ifaddr 0 mcast_querier 0 mcast_hash_elasticity 4 mcast_hash_max 512 mcast_last_member_count 2 mcast_startup_query_count 2 mcast_last_member_interval 100 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000 mcast_startup_query_interval 3125
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe6e:c522/64 scope link
       valid_lft forever preferred_lft forever
```

iptablesでNAPTしているので、natテーブルを確認  
docker0のブリッジがIPマスカレードするルールが存在しています

```
[root@sugi-docker-registory ~]# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             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  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere           
```

filterテーブルも確認

```
[root@sugi-docker-registory ~]# iptables -L -t filter
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

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  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
```

## ローカルレジストリをコンテナとして実行
以下コマンドを実行して、ローカルレジストリをコンテナとして実行します  
オプションの説明
-d : コンテナ実行をバックグラウンドで実行する。また、コンテナーIDを表示する。
-p : コンテナのポートをホストに公開します。 ホスト側のポート：コンテナ側のポート
--restart : コンテナが存在しているときの、restartのポリシーを設定します
--name : コンテナに名前を指定します
registory:2 : コンテナを実行する際に指定するイメージ名の指定。存在しない場合はDockerHubからダウンロードする

```
docker run -d -p 5000:5000 --restart=always --name registry registry:2
```

実行例

```
[root@sugi-docker-registory ~]# docker run -d -p 5000:5000 --restart=always --name registry registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
81033e7c1d6a: Pull complete
b235084c2315: Pull complete
c692f3a6894b: Pull complete
ba2177f3a70e: Pull complete
a8d793620947: Pull complete
Digest: sha256:672d519d7fd7bbc7a448d17956ebeefe225d5eb27509d8dc5ce67ecb4a0bce54
Status: Downloaded newer image for registry:2
e03c7a5b8ded2a9b68a045eba91eccb15c7567ef51d464719528c1757cecda43
```

registryコンテナが稼働している

```
[root@sugi-docker-registory ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
e03c7a5b8ded        registry:2          "/entrypoint.sh /etc…"   2 minutes ago       Up 2 minutes        0.0.0.0:5000->5000/tcp   registry
```

## コンテナ実行後の各種状態を確認
コンテナのネットワークは以下の画像のような接続になっています

![001.png](https://qiita-image-store.s3.amazonaws.com/0/104247/4e6a3529-4316-92c4-a1f9-f231d70c896b.png)

docker0に、veth25382cfという名前のvethが接続されています

```
[root@sugi-docker-registory ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242ac6ec522       no              veth25382cf
```

ipコマンドでインターフェースを確認  
veth25382cf が veth として存在していることが確認できます
veth25382cf の対向のインターフェース番号16のものは、ホスト側からは確認できません
ネットワークネームスペースを使用してネットワークが分離されているため、ホスト側からでは確認することが出来ません

```
[root@sugi-docker-registory ~]# ip -d a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0
    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
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:50:56:98:57:73 brd ff:ff:ff:ff:ff:ff promiscuity 0
    inet 192.168.120.210/24 brd 192.168.120.255 scope global ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::98a0:413d:6b71:8fbd/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:6e:c5:22 brd ff:ff:ff:ff:ff:ff promiscuity 0
    bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time 30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q bridge_id 8000.2:42:ac:6e:c5:22 designated_root 8000.2:42:ac:6e:c5:22 root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0 hello_timer    0.00 tcn_timer    0.00 topology_change_timer    0.00 gc_timer  195.44 vlan_default_pvid 1 group_fwd_mask 0 group_address 01:80:c2:00:00:00 mcast_snooping 1 mcast_router 1 mcast_query_use_ifaddr 0 mcast_querier 0 mcast_hash_elasticity 4 mcast_hash_max 512 mcast_last_member_count 2 mcast_startup_query_count 2 mcast_last_member_interval 100 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000 mcast_startup_query_interval 3125
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe6e:c522/64 scope link
       valid_lft forever preferred_lft forever
17: veth25382cf@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
    link/ether be:b6:f6:2b:62:43 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 1
    veth
    bridge_slave state forwarding priority 32 cost 2 hairpin off guard off root_block off fastleave off learning on flood on port_id 0x8001 port_no 0x1 designated_port 32769 designated_cost 0 designated_bridge 8000.2:42:ac:6e:c5:22 designated_root 8000.2:42:ac:6e:c5:22 hold_timer    0.00 message_age_timer    0.00 forward_delay_timer    0.00 topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off mcast_router 1 mcast_fast_leave off mcast_flood on
    inet6 fe80::bcb6:f6ff:fe2b:6243/64 scope link
       valid_lft forever preferred_lft forever
```

iptablesのnatテーブルを確認  
registryコンテナ用のマスカレード、DNAT用のルールが追加されています。

```
[root@sugi-docker-registory ~]#  iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             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  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:commplex-main     ←追加されている

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp dpt:commplex-main to:172.17.0.2:5000     ←追加されている
```

registryコンテナのインターフェースを確認します  
eth0@if17 が存在していて、docker0ブリッジと同一のセグメントに接続されています。  
veth「veth25382cf」のもう片方側が、registryコンテナ内(ネットワークネームスペース内)に接続されています

```
[root@sugi-docker-registory ~]# docker exec -it registry ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
```

## コンテナのネットワークネームスペースに潜り込む
コンテナを普通に起動しただけでは、ip netns コマンドでは、ネットワークネームスペースを確認することが出来ません
ip netnsコマンドは、/var/run/netns配下のファイルを使用して表示していますが、
Dockerを使用してコンテナを作成すると、ここのディレクトリにはファイルが作成されません。
Dockerでは、/proc/16360/ns/net にネットワーク識別子のシンボリックリンクが作成されています。

まずは、registryコンテナのPIDを確認します

```
[root@sugi-docker-registory ~]# docker inspect registry --format '{{.State.Pid}}'
16360
```

念のためpsコマンドでも確認

```
[root@sugi-docker-registory ~]# ps aux | grep 16360
root     16360  0.0  0.1  22028  7752 ?        Ssl  00:07   0:00 registry serve /etc/docker/registry/config.yml
```

上記プロセスが使用しているネットワーク識別子を確認します

```
[root@sugi-docker-registory ~]# ls -la /proc/16360/ns/net
lrwxrwxrwx 1 root root 0 Mar 10 00:07 /proc/16360/ns/net -> net:[4026532447]
```

/proc/16360/ns/net を /var/run/netns 配下に置くと、ip netns コマンドで認識することが出来ます  
以下のようにシンボリックリンクを作成します

```
mkdir -p /var/run/netns/
ln -s /proc/16360/ns/net /var/run/netns/registry-netns
```

これにより、ip netnsコマンドでネットワークネームスペースを認識することが出来ました  
ここまで出来ると、OpenStackのNeutronでデバッグしてきたノウハウが使用できます

```
[root@sugi-docker-registory ~]# ip netns
registry-netns (id: 0)
```

ネットワークネームスペースでbashを起動します

```
ip netns exec registry-netns bash
```

インターフェースを確認します。
registryコンテナ用に分離されているネームスペース内でインターフェースを確認できます

```
[root@sugi-docker-registory ~]# ip -d a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
    veth
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
```

ルーティングテーブルを確認します

```
[root@sugi-docker-registory ~]# 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.2
```

余談ですが・・・現在ログインしているネットワークネームスペース名を以下コマンドで確認することが出来ます

registry-netns用のネームスペース内で実行  
ログインしているネームスペースの名前が表示されます

```
[root@sugi-docker-registory ~]# ip netns identify
registry-netns
```

ホストOS側で実行  
何も表示されません  

```
[root@sugi-docker-registory ~]# ip netns identify
[root@sugi-docker-registory ~]#
```

間違ってホストOS側に居ることに気が付かずにexitしてしまうあるあるを、回避することが出来ますね。

## IPマスカレードのパケットを確認
registryコンテナから、外部ネットワークのGWへpingを行います

```
docker exec -it registry ping 192.168.120.254
```

通信イメージは以下の通り

![002.png](https://qiita-image-store.s3.amazonaws.com/0/104247/15263566-4f80-35a9-326c-c68c327f81e7.png)

コンテナ側のeth0でtcpdump  
GWと通信が出来ています。
MacAddressを見ると、コンテナ側のeth0と、ホスト側のdocker0で通信を行っています。

```
[root@sugi-docker-registory ~]# ip netns exec registry-netns tcpdump -e -s 0 -nn -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
01:34:46.653792 02:42:ac:11:00:02 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 192.168.120.254: ICMP echo request, id 22272, seq 51, length 64
01:34:46.654201 02:42:ac:6e:c5:22 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.2: ICMP echo reply, id 22272, seq 51, length 64
01:34:47.654200 02:42:ac:11:00:02 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 192.168.120.254: ICMP echo request, id 22272, seq 52, length 64
01:34:47.654666 02:42:ac:6e:c5:22 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.2: ICMP echo reply, id 22272, seq 52, length 64
01:34:48.654465 02:42:ac:11:00:02 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 192.168.120.254: ICMP echo request, id 22272, seq 53, length 64
01:34:48.654809 02:42:ac:6e:c5:22 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.2: ICMP echo reply, id 22272, seq 53, length 64
01:34:49.654694 02:42:ac:11:00:02 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 192.168.120.254: ICMP echo request, id 22272, seq 54, length 64
01:34:49.655135 02:42:ac:6e:c5:22 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.2: ICMP echo reply, id 22272, seq 54, length 64
01:34:50.654929 02:42:ac:11:00:02 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 192.168.120.254: ICMP echo request, id 22272, seq 55, length 64
01:34:50.655262 02:42:ac:6e:c5:22 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.2: ICMP echo reply, id 22272, seq 55, length 64
```

ホスト側の物理NICでtcpdump
IPマスカレードが行われており、物理NICのens192のIPアドレスを使用して通信されています
MacAddressを見ると、ホスト側のens192とGWで通信を行っています。

```
[root@sugi-docker-registory ~]# tcpdump -e -s 0 -nn -i ens192 not port 22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
01:33:00.470572 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 21248, seq 161, length 64
01:33:00.470898 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 21248, seq 161, length 64
01:33:01.470760 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 21248, seq 162, length 64
01:33:01.471002 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 21248, seq 162, length 64
01:33:02.470960 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 21248, seq 163, length 64
01:33:02.471199 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 21248, seq 163, length 64
01:33:03.471189 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 21248, seq 164, length 64
01:33:03.471407 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 21248, seq 164, length 64
01:33:04.471379 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 21248, seq 165, length 64
01:33:04.471620 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 21248, seq 165, length 64
01:33:05.471573 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 21248, seq 166, length 64
01:33:05.471801 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 21248, seq 166, length 64
01:33:06.471879 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 21248, seq 167, length 64
01:33:06.472236 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 21248, seq 167, length 64
```

## 2個目のコンテナを作成し、ネットワークの接続を確認
2個目のコンテナを作成します
適当にcentosイメージをDockerHubからダウンロードします

```
docker pull centos
```

実行例

```
[root@sugi-docker-registory ~]# docker pull centos
Using default tag: latest
latest: Pulling from library/centos
5e35d10a3eba: Pull complete
Digest: sha256:dcbc4e5e7052ea2306eed59563da1fec09196f2ecacbe042acbdcd2b44b05270
Status: Downloaded newer image for centos:latest
```

docker image に追加されている

```
[root@sugi-docker-registory ~]#
[root@sugi-docker-registory ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              2d194b392dd1        3 days ago          195MB  ←追加されている
registry            2                   d1fd7d86a825        8 weeks ago         33.3MB
hello-world         latest              f2a91732366c        3 months ago        1.85kB
```

2個目のコンテナを作成します

```
docker run -d -p 5001:5001 --name test_centos -it centos /bin/bash
```

実行例

```
[root@sugi-docker-registory ~]# docker run -d --name test_centos -it centos /bin/bash
2fec8a04d74bbe8c5e6f4824a1a091922a2160d3f530fc4194fa8a7e2a2befd8
```

CentOSのDockerイメージには、ipコマンドがインストールされていないので、インストールを行う  
ついでにtcpdumpもインストールを行う

```
docker exec -it test_centos yum install iproute tcpdump
```

## 2個目のコンテナ実行後の各種状態を確認
コンテナのネットワークは以下の画像のような接続になっています

![003.png](https://qiita-image-store.s3.amazonaws.com/0/104247/e40b2a5d-3a93-fd87-b7aa-6fabb9685099.png)

docker0に、 vetha8f91f8 という名前のvethが接続されています

```
[root@sugi-docker-registory ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242ac6ec522       no              veth25382cf
                                                        vetha8f91f8    ←追加
```

ipコマンドでインターフェースを確認  
vetha8f91f8 が veth として新たに存在していることが確認できます
vetha8f91f8 の対向のインターフェース番号24のものは、ホスト側からは確認できません
ネットワークネームスペースを使用してネットワークが分離されているため、ホスト側からでは確認することが出来ません

```
[root@sugi-docker-registory ~]# ip -d a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0
    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
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:50:56:98:57:73 brd ff:ff:ff:ff:ff:ff promiscuity 0
    inet 192.168.120.210/24 brd 192.168.120.255 scope global ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::98a0:413d:6b71:8fbd/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:6e:c5:22 brd ff:ff:ff:ff:ff:ff promiscuity 0
    bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time 30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q bridge_id 8000.2:42:ac:6e:c5:22 designated_root 8000.2:42:ac:6e:c5:22 root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0 hello_timer    0.00 tcn_timer    0.00 topology_change_timer    0.00 gc_timer  269.16 vlan_default_pvid 1 group_fwd_mask 0 group_address 01:80:c2:00:00:00 mcast_snooping 1 mcast_router 1 mcast_query_use_ifaddr 0 mcast_querier 0 mcast_hash_elasticity 4 mcast_hash_max 512 mcast_last_member_count 2 mcast_startup_query_count 2 mcast_last_member_interval 100 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000 mcast_startup_query_interval 3125
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe6e:c522/64 scope link
       valid_lft forever preferred_lft forever
17: veth25382cf@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
    link/ether be:b6:f6:2b:62:43 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 1
    veth
    bridge_slave state forwarding priority 32 cost 2 hairpin off guard off root_block off fastleave off learning on flood on port_id 0x8001 port_no 0x1 designated_port 32769 designated_cost 0 designated_bridge 8000.2:42:ac:6e:c5:22 designated_root 8000.2:42:ac:6e:c5:22 hold_timer    0.00 message_age_timer    0.00 forward_delay_timer    0.00 topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off mcast_router 1 mcast_fast_leave off mcast_flood on
    inet6 fe80::bcb6:f6ff:fe2b:6243/64 scope link
       valid_lft forever preferred_lft forever
25: vetha8f91f8@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
    link/ether c6:b8:c4:ac:5e:22 brd ff:ff:ff:ff:ff:ff link-netnsid 1 promiscuity 1
    veth
    bridge_slave state forwarding priority 32 cost 2 hairpin off guard off root_block off fastleave off learning on flood on port_id 0x8002 port_no 0x2 designated_port 32770 designated_cost 0 designated_bridge 8000.2:42:ac:6e:c5:22 designated_root 8000.2:42:ac:6e:c5:22 hold_timer    0.00 message_age_timer    0.00 forward_delay_timer    0.00 topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off mcast_router 1 mcast_fast_leave off mcast_flood on
    inet6 fe80::c4b8:c4ff:feac:5e22/64 scope link
       valid_lft forever preferred_lft forever
```

iptablesのnatテーブルを確認  
test_centosコンテナ用のマスカレード、DNAT用のルールが追加されています。

```
[root@sugi-docker-registory ~]# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             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  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:commplex-main
MASQUERADE  tcp  --  172.17.0.3           172.17.0.3           tcp dpt:commplex-link  ←追加されている

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp dpt:commplex-main to:172.17.0.2:5000
DNAT       tcp  --  anywhere             anywhere             tcp dpt:commplex-link to:172.17.0.3:5001  ←追加されている
```

test_centosコンテナのインターフェースを確認します  
eth0@if25 が存在していて、docker0ブリッジと同一のセグメントに接続されています。  

```
[root@sugi-docker-registory ~]# docker exec -it test_centos ip -d a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
    veth
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
```

## コンテナ同士の通信を確認
test_centos → registry コンテナへPingが届きます。  
docker0 ブリッジに接続されているので、互いにL2で通信が可能です

```
[root@sugi-docker-registory ~]# docker exec -it test_centos ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.164 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.082 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.084 ms
```

tcpdumpを実行します  
MacAddressでみても、コンテナ同士で直に通信を行っています

```
[root@sugi-docker-registory ~]# docker exec -it test_centos tcpdump -e -s0 -nn -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:47:31.104219 02:42:ac:11:00:03 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 172.17.0.2: ICMP echo request, id 190, seq 26, length 64
17:47:31.104283 02:42:ac:11:00:02 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 172.17.0.3: ICMP echo reply, id 190, seq 26, length 64
17:47:32.104234 02:42:ac:11:00:03 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 172.17.0.2: ICMP echo request, id 190, seq 27, length 64
17:47:32.104296 02:42:ac:11:00:02 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 172.17.0.3: ICMP echo reply, id 190, seq 27, length 64
17:47:33.104286 02:42:ac:11:00:03 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 172.17.0.2: ICMP echo request, id 190, seq 28, length 64
17:47:33.104389 02:42:ac:11:00:02 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 172.17.0.3: ICMP echo reply, id 190, seq 28, length 64
17:47:34.104236 02:42:ac:11:00:03 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 172.17.0.2: ICMP echo request, id 190, seq 29, length 64
17:47:34.104299 02:42:ac:11:00:02 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 172.17.0.3: ICMP echo reply, id 190, seq 29, length 64
17:47:35.104208 02:42:ac:11:00:03 > 02:42:ac:11:00:02, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 172.17.0.2: ICMP echo request, id 190, seq 30, length 64
17:47:35.104251 02:42:ac:11:00:02 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 172.17.0.2 > 172.17.0.3: ICMP echo reply, id 190, seq 30, length 64
```

## test_centos → GW へ通信を行う

通信のイメージは以下の通り

![003.png](/knowledge/open.file/download?fileNo=3216)


test_centos → GW へpingを行う

```
docker exec -it test_centos ping 192.168.120.254
```

test_centos の eth0 で tcpdump  
MacAddressは、同様に、コンテナ内のeth0とホスト側のdocker0で通信を行っています

```
[root@sugi-docker-registory ~]# docker exec -it test_centos tcpdump -e -s0 -nn -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:49:41.564237 02:42:ac:11:00:03 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 192.168.120.254: ICMP echo request, id 210, seq 7, length 64
17:49:41.564586 02:42:ac:6e:c5:22 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.3: ICMP echo reply, id 210, seq 7, length 64
17:49:42.564207 02:42:ac:11:00:03 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 192.168.120.254: ICMP echo request, id 210, seq 8, length 64
17:49:42.564562 02:42:ac:6e:c5:22 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.3: ICMP echo reply, id 210, seq 8, length 64
17:49:43.564284 02:42:ac:11:00:03 > 02:42:ac:6e:c5:22, ethertype IPv4 (0x0800), length 98: 172.17.0.3 > 192.168.120.254: ICMP echo request, id 210, seq 9, length 64
17:49:43.564597 02:42:ac:6e:c5:22 > 02:42:ac:11:00:03, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 172.17.0.3: ICMP echo reply, id 210, seq 9, length 64
```

ホスト側の物理NIC ens192 で tcpdump  
同様に、ens192 のIPアドレスでマスカレードされています

```
[root@sugi-docker-registory ~]# tcpdump -e -s 0 -nn -i ens192 not port 22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens192, link-type EN10MB (Ethernet), capture size 262144 bytes
02:51:10.693235 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 218, seq 20, length 64
02:51:10.693442 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 218, seq 20, length 64
02:51:11.693249 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 218, seq 21, length 64
02:51:11.693573 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 218, seq 21, length 64
02:51:12.693235 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 218, seq 22, length 64
02:51:12.693572 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 218, seq 22, length 64
02:51:13.693234 00:50:56:98:57:73 > 00:50:56:aa:36:d5, ethertype IPv4 (0x0800), length 98: 192.168.120.210 > 192.168.120.254: ICMP echo request, id 218, seq 23, length 64
02:51:13.693589 00:50:56:aa:36:d5 > 00:50:56:98:57:73, ethertype IPv4 (0x0800), length 98: 192.168.120.254 > 192.168.120.210: ICMP echo reply, id 218, seq 23, length 64
```

# 参考URL
Dockerとnetnsの関係
http://enakai00.hatenablog.com/entry/20140424/1398321672
https://qiita.com/ukinau/items/92740bd0bafc1e7427c5

既存コンテナのbashへ接続方法 attachとexecの違い
https://qiita.com/RyoMa_0923/items/9b5d2c4a97205692a560

DockerRegistryの構築
https://docs.docker.com/registry/