LoginSignup
4
7

More than 3 years have passed since last update.

Dockerネットワーク技術について理解を深めてみた

Posted at

Dockerネットワーク技術について理解を深める

Dockerコンテナ内で、名前解決ができない問題に直面し悩まされた。ホストOS側のFirewallのNAPT設定を有効にすることで解決できたが、Dockerネットワーク機能について理解が不足していたので、少し学習してみた。

問題の『事象』と『対策』

Dockerコンテナ内で名前解決ができていない。

$ docker run -it busybox ping -c 1 -4 google.com
ping: bad address 'google.com'

ホストOS側では名前解決ができている。

$ ping -c 1 -4 google.com
PING google.com (216.58.197.206) 56(84) bytes of data.
64 bytes from nrt13s48-in-f206.1e100.net (216.58.197.206): icmp_seq=1 ttl=56 time=1.16 ms

--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.163/1.163/1.163/0.000 ms

外部へのIP疎通はできている。

$ docker run -it busybox ping -c 1 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=55 time=2.921 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.921/2.921/2.921 ms

どうやらDockerは外部と通信するために、IPマスカレードを使ったNATにより実現されており、ルーティングがiptablesのフォワードルールの形式で自動設定されているようだ。そこで、Firewall側でNAPT設定を有効にしてやることで解決した。

$ firewall-cmd --add-masquerade --permanent
$ firewall-cmd --reload
$ firewall-cmd --list-all --permanent | grep masquerade
  masquerade: yes

Dockerコンテナ内で名前解決に成功し、疎通に成功した。

$ docker run -it busybox ping -c 1 -4 google.com
PING google.com (216.58.197.174): 56 data bytes
64 bytes from 216.58.197.174: seq=0 ttl=55 time=1.659 ms

--- google.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.659/1.659/1.659 ms

Dockerネットワークの構成

Dockerネットワークの構成を図示してみた。

各コンテナ及びホストOSは、仮想ブリッジ(docker0)がNAT機能を担うことによって、各コンテナにIPアドレスが割り振られている。

つまり、コンテナから外部へ通信する場合は、仮想ブリッジ(docker0)経由で、NAT変換(IPマスカレード)が行われることで、通信を実現している。

この仮想ブリッジ(docker0)のNAT変換機能は、ホストOSのiptablesが提供するNAT機能によって、機能を実現させている。

各コンテナ(eth0)と仮想ブリッジ(docker0)を繋いでいるのが、仮想NIC(veth)である。仮想NIC(veth)は、各コンテナ内のeth0と、仮想ブリッジ(docker0)間の通信を実現するための、レイヤ2のインターフェース機能となります。コンテナ内のeth0とvethは、スイッチを経由せずに直接LANケーブルで接続されているイメージです。

コマンドで確認

仮想ブリッジ(docker0)と、仮想NIC(veth51fab7f@if52)が生成されていることがわかる。また、ホストOSの物理NIC(eth0)と仮想ブリッジ(docker0)のネットワークセグメントが異なっていることがわかる。

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether XX:XX:XX:1b:13:95 brd ff:ff:ff:ff:ff:ff
    inet XXX.XXX.19.149/23 brd XXX.XXX.19.255 scope global dynamic noprefixroute eth0
       valid_lft 2868003sec preferred_lft 2868003sec
    inet6 XXXX:XXXX:1801:409:XXX:XXX:19:149/128 scope global dynamic noprefixroute
       valid_lft 2868005sec preferred_lft 2868005sec
    inet6 XXXX::X:XXXX:fe1b:1395/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether XX:XX:XX:85:63:76 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 XXXX::XX:XXXX:fe85:6376/64 scope link
       valid_lft forever preferred_lft forever
53: veth51fab7f@if52: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether XX:XX:XX:b9:e6:e0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 XXXX::XXXX:XXXX:feb9:e6e0/64 scope link
       valid_lft forever preferred_lft forever

172.17.0.0/16(docker0)のネットワーク範囲から、0.0.0.0/0のネットワーク範囲を宛先とする場合、送信元IPをホストOS側の物理NICのIPへ変換するように設定されている。

$ iptables -t nat -nL -v | grep -A 3 POSTROUTING
Chain POSTROUTING (policy ACCEPT 124 packets, 8216 bytes)
 pkts bytes target     prot opt in     out     source               destination
   29  1440 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0

仮想ブリッジ(docker0)と仮想NIC(veth)の接続状況を確認してみる。しっかりとveth51fab7f@if52が接続されていることがわかる。

$ bridge link show docker0
53: veth51fab7f@if52: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0 state forwarding priority 32 cost 2

コンテナ内からルーティングを確認してみた。

# docker run -it busybox ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 scope link  src 172.17.0.3

コンテナ内からgoogle.comへの通信で、NATされる様子を確認してみた。

# docker run -it busybox traceroute -n google.com
traceroute to google.com (216.58.197.206), 30 hops max, 46 byte packets
 1  172.17.0.1  0.006 ms  0.003 ms  0.003 ms ← Docker側のゲートウェイ
 2  XXX.XX.18.2  0.486 ms  0.165 ms  0.362 ms ← ホストOS側のゲートウェイ
 3  省略
4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7