docker コンテナ・ネットワーク のまとめ
デフォルトネットワークで EXPOSE 指定の無いポートで通信できちゃう現象に出会いました。 あれ?ネットワーク作ってないのに・・・
Dockerの コンテナネットワークについて、 きちんと理解できていないような気がしてきたので きちんと調べてみました。
環境
root@ubuntu:~# docker version Client: Version: 17.12.0-ce API version: 1.35 Go version: go1.9.2 Git commit: c97c6d6 Built: Wed Dec 27 20:11:14 2017 OS/Arch: linux/amd64 Server: Engine: Version: 17.12.0-ce API version: 1.35 (minimum version 1.12) Go version: go1.9.2 Git commit: c97c6d6 Built: Wed Dec 27 20:09:47 2017 OS/Arch: linux/amd64 Experimental: false
調査
準備
テストコンテナをデフォルトネットワークに2つ立てます
# docker run -dP --name test1 moremagic/ubuntu-sshd # docker run -dP --name test2 moremagic/ubuntu-sshd
こんな感じになります
root@ubuntu:~# docker network inspect bridge [ { "Name": "bridge", "Id": "ef63456b96b3b25c816de8252b5e7d507380eec7c08adf7a25a5df00b24ba861", "Created": "2018-01-29T12:02:13.127525987+09:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "39018bcf7003c48e8fe4356c98d83dfa0e4e0536879fd42fef02defc393ea2f9": { "Name": "test2", "EndpointID": "5df80c71fbe1307bff8e8494bf8df70c38d9349a86cc2344e7fbeb95ff84a165", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "ccb0aa9e8ec770dd552aefcf811c709497cfb6b616ae4a0d8d56ac6c4f795a5d": { "Name": "test1", "EndpointID": "3a769eabedb861821d796e10b93c10d99e54e336b0a9ee539a5c5d303aa8169b", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
それぞれのコンテナで 検証ツール類(ping, socat) をインストールしておきます
test1コンテナ
root@ubuntu:~# docker exec -ti test1 bash root@ccb0aa9e8ec7:/# apt update -y && apt install -y inetutils* socat
test2コンテナ
root@ubuntu:~# docker exec -ti test2 bash root@39018bcf7003:/# apt update -y && apt install -y inetutils* socat
疎通確認
デフォルトネットワークで検証
test1 → test2 へ ping
root@ubuntu:~# docker exec -ti test1 bash root@ccb0aa9e8ec7:/# root@ccb0aa9e8ec7:/# ping test2 ping: unknown host test2 root@ccb0aa9e8ec7:/# ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.057 ms 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.080 ms ^C --- 172.17.0.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1016ms rtt min/avg/max/mdev = 0.057/0.068/0.080/0.014 ms
ホスト名でのPing はできないけど IPアドレスでのPing はできる
test1 -> test2 に SSH(EXPOSEしているポートを使う)
root@ccb0aa9e8ec7:/# ssh test2 ssh: Could not resolve hostname test2: Name or service not known root@ccb0aa9e8ec7:/# ssh 172.17.0.3 root@172.17.0.3's password: Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.13.0-31-generic x86_64) root@39018bcf7003:~#
ホスト名でのSSH はできないけど IPアドレスでのSSH はできる
test1 -> test2 に UDP(EXPOSEしてないポートを使う) まずtest2 でリッスンしておきます
root@ubuntu:~# docker exec -ti test2 bash root@39018bcf7003:/# socat udp-listen:70000 stdout
test1 から test2へ接続します
root@ubuntu:~# docker exec -ti test1 bash root@ccb0aa9e8ec7:/# socat udp-connect:172.17.0.3:70000 stdin
ここで何か入力すると、test2側で入力した文字列が出力されました。
test1 -> test2 に TCP(EXPOSEしてないポートを使う) まずtest2 でリッスンしておきます
root@ubuntu:~# docker exec -ti test2 bash root@39018bcf7003:/# socat tcp-listen:70000 stdout
test1 から test2へ接続します
root@ubuntu:~# docker exec -ti test1 bash root@ccb0aa9e8ec7:/# socat tcp-connect:172.17.0.3:70000 stdin
ここで何か入力すると、test2側で入力した文字列が出力されました。
EXPOSE していない TCP, UDPポートへの接続はできました
Bridgeネットワーク(mynet)での検証
ネットワークを作成します
root@ubuntu:~# docker network create mynet 928f7bb31aeb52d5f2fc6416e22986e50f9d83b50b159819e11a7f37b6bb5398 root@ubuntu:~# docker network ls NETWORK ID NAME DRIVER SCOPE ef63456b96b3 bridge bridge local e237038b6196 host host local 928f7bb31aeb mynet bridge local b17d8a6746bc none null local
test1
、test2
コンテナを mynet ネットワークに所属させます
root@ubuntu:~# docker network disconnect bridge test1 root@ubuntu:~# docker network disconnect bridge test2 root@ubuntu:~# docker network connect mynet test1 root@ubuntu:~# docker network connect mynet test2 root@ubuntu:~# docker network inspect mynet [ { "Name": "mynet", "Id": "928f7bb31aeb52d5f2fc6416e22986e50f9d83b50b159819e11a7f37b6bb5398", "Created": "2018-02-13T09:06:28.009216768+09:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "39018bcf7003c48e8fe4356c98d83dfa0e4e0536879fd42fef02defc393ea2f9": { "Name": "test2", "EndpointID": "926e5878a1fe5c2c59f35fe27c336c726cec46117bfa876563d6b563fa812ba6", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", "IPv6Address": "" }, "ccb0aa9e8ec770dd552aefcf811c709497cfb6b616ae4a0d8d56ac6c4f795a5d": { "Name": "test1", "EndpointID": "eca65cd1e594a360992333ad8655f2845a5c237fcc723b63d65ccd4ccec77a32", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
test1-> test2 (PING)
root@ubuntu:~# docker exec -ti test1 bash root@ccb0aa9e8ec7:/# ping test2 PING test2 (172.18.0.3) 56(84) bytes of data. 64 bytes from test2.mynet (172.18.0.3): icmp_seq=1 ttl=64 time=0.073 ms 64 bytes from test2.mynet (172.18.0.3): icmp_seq=2 ttl=64 time=0.112 ms ^C --- test2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1028ms rtt min/avg/max/mdev = 0.073/0.092/0.112/0.021 ms
ping 応答があった
test1-> test2 (UDP)
root@ubuntu:~# docker exec -ti test2 bash root@39018bcf7003:/# socat udp-listen:70000 stdout
root@ubuntu:~# docker exec -ti test1 bash root@ccb0aa9e8ec7:/# socat udp-connect:test2:70000 stdin
入力したデータが表示された
test1-> test2 (TCP)
root@ubuntu:~# docker exec -ti test2 bash root@39018bcf7003:/# socat tcp-listen:70000 stdout
root@ubuntu:~# docker exec -ti test1 bash root@ccb0aa9e8ec7:/# socat tcp-connect:test2:70000 stdin
入力したデータが表示された
まとめ
- デフォルト・ネットワークでは コンテナ名での名前解決は出来ない
ブリッジネットワークであればコンテナ名での名前解決は可能
同一ネットワーク同士であれば EXPOSE していないポートでも コンテナ間通信は可能
- デフォルトネットワークでも EXPOSE していないポートでも コンテナ間通信は可能(← これを知らなかった)
思い込みはダメね・・・orz
資料
Docker コンテナ・ネットワークの理解 — Docker-docs-ja 17.06.Beta ドキュメント
moremagic
2018-02-13