Dockerのネットワークを理解する!(2)

前回の記事でそもそものブリッジネットワークについてと、Docker Bridge について書きました。

baubaubau.hatenablog.com

今回は新しくBridgeネットワークを作ってみたいと思います。

デフォルトのBridgeネットワークとUser Specific Bridgeネットワークの違い

デフォルトで用意されているBridgeネットワークと、ユーザが定義するBridgeネットワークには違いがあるようです。

docs.docker.com

違いは以下の5つ。

  • ネットワークの独立性、コンテナの相互運用性が高い
  • DNSによる名前解決
  • 動的なネットワークへの接続・切断
  • 環境変数の共有方法

公式サイトのチュートリアルをやってみる

作成するネットワークの概要は以下の図です。alpine-netというネットワークが新しく作成するネットワークになります。

f:id:bau1537:20200112193635j:plain

まずは新しいネットワークブリッジをalpine-netという名前で作成します。

bookstore@ [/Users/bookstore] %
> docker network create --driver bridge alpine-net
2dd3cc99e0772fbe364e6c88d397106e89b8510f5bb603cf0228b4ee48cabf8b
bookstore@ [/Users/bookstore] %
> docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
2dd3cc99e077        alpine-net          bridge              local
db5018912e91        bridge              bridge              local
1553d31b2a95        host                host                local
a1caa97e1265        none                null                local

inspect で詳細を確認。

bookstore@ [/Users/bookstore] %
> docker network inspect alpine-net
[
    {
        "Name": "alpine-net",
        "Id": "2dd3cc99e0772fbe364e6c88d397106e89b8510f5bb603cf0228b4ee48cabf8b",
        "Created": "2020-01-12T03:07:18.0019291Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.27.0.0/16",
                    "Gateway": "172.27.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

上記の内容をよく見てみるとGateway172.27.0.1 になっていますね。このアドレスはデフォルトで作成されているブリッジネットワークとは異なるアドレスのため、別のネットワークになっていることが確認できます。

alpine-netに3つのコンテナを、デフォルトネットワークに2つのコンテナを接続させます。この内一つのコンテナはどちらのネットワークにも接続させます。

$ docker run -dit --name alpine1 --network alpine-net alpine ash

$ docker run -dit --name alpine2 --network alpine-net alpine ash

$ docker run -dit --name alpine3 alpine ash

$ docker run -dit --name alpine4 --network alpine-net alpine ash

$ docker network connect bridge alpine4

この時点でコンテナはこんな感じで動いています。

bookstore@ [/Users/bookstore] %
> docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
5c1829997ea2        alpine              "ash"               27 seconds ago       Up 26 seconds                           alpine4
8014dad07fe1        alpine              "ash"               54 seconds ago       Up 52 seconds                           alpine3
72b2cc6163b4        alpine              "ash"               About a minute ago   Up About a minute                       alpine2
15a8760749a9        alpine              "ash"               3 minutes ago        Up 3 minutes                            alpine1

ここでashというコマンドを実行していますがこれはシェルのことですね。

この時点でデフォルトのブリッジネットワークと、alpine-netネットワークは以下のような状態になっています。

> docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "db5018912e91a88c4a88449c26397370cddf5df11db5901fd3a84fe19fb9243c",
        "Created": "2020-01-01T02:47:27.942409352Z",
        "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": {
            "5c1829997ea2d36e5e2d9a121d6390068755b6c9ec9bbc4253fbc28ce2882a7c": {
                "Name": "alpine4",
                "EndpointID": "6052330789d78fe2497850ea57a6342ac59e897beeb4c1947f546c2ca5283116",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "8014dad07fe189685ab7302fcd849f5c8fd20f13c53020dd8b0e0a598d5b3f7d": {
                "Name": "alpine3",
                "EndpointID": "679be500508c6322fbcdc4de47b0f45580d4ebf0eaee932eeee2b815250c5741",
                "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": {}
    }
]
> docker network inspect alpine-net
[
    {
        "Name": "alpine-net",
        "Id": "2dd3cc99e0772fbe364e6c88d397106e89b8510f5bb603cf0228b4ee48cabf8b",
        "Created": "2020-01-12T03:07:18.0019291Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.27.0.0/16",
                    "Gateway": "172.27.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "15a8760749a9dde061106842b3f7d33782dae38f3ed01a3960a9739a86a0490d": {
                "Name": "alpine1",
                "EndpointID": "eb299724e48f455074456e8a12367bd30e943a0edcef1254e999e121484af1ce",
                "MacAddress": "02:42:ac:1b:00:02",
                "IPv4Address": "172.27.0.2/16",
                "IPv6Address": ""
            },
            "5c1829997ea2d36e5e2d9a121d6390068755b6c9ec9bbc4253fbc28ce2882a7c": {
                "Name": "alpine4",
                "EndpointID": "0452ab71b7439193807f55329f99617e054ef94ccc63dd3ae4ef9e54a99e2952",
                "MacAddress": "02:42:ac:1b:00:04",
                "IPv4Address": "172.27.0.4/16",
                "IPv6Address": ""
            },
            "72b2cc6163b4efae07f680a9b40618338aad82cc21c6f9e28ce0f64d37ff4970": {
                "Name": "alpine2",
                "EndpointID": "1dc7c262dc6f47f5f575518738ede0aca836279e739fafe5601ad21546831e05",
                "MacAddress": "02:42:ac:1b:00:03",
                "IPv4Address": "172.27.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

ここでalpine-netに接続されているコンテナ間でpingが打てるかを試してみます。alpine1コンテナに接続し、alpine4、alpine2に対してpingを打ったのが以下になります。ここでコンテナ名をホスト名としてpingコマンドを叩いているが、これはDockerの機能で、最初の方で説明したデフォルトのブリッジネットワークとの違いになると思います。つまり、DNSが有効になってコンテナ名でホストを指定することができているわけですね。

bookstore@ [/Users/bookstore] %
> docker container attach alpine1
/ # ping -c 2 alpine2
PING alpine2 (172.27.0.3): 56 data bytes
64 bytes from 172.27.0.3: seq=0 ttl=64 time=0.108 ms
64 bytes from 172.27.0.3: seq=1 ttl=64 time=0.271 ms

--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.108/0.189/0.271 ms
/ # ping -c 2 alpine4
PING alpine4 (172.27.0.4): 56 data bytes
64 bytes from 172.27.0.4: seq=0 ttl=64 time=0.316 ms
64 bytes from 172.27.0.4: seq=1 ttl=64 time=0.149 ms

--- alpine4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.149/0.232/0.316 ms

ただ、alpine-netに接続されていないalpine3コンテナには、alpine1コンテナからは接続することはできません。これはコンテナ名を指定しても、IPアドレスを指定しても、接続することはできません。

/ # ping -c 2 alpine3
ping: bad address 'alpine3'
/ # ping -c 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes

--- 172.17.0.2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

今度はデフォルトのブリッジネットワークと、alpine-netの両方に接続されているalpine4コンテナにアタッチし、pingを打ってみます。先程は接続できなかったalpine3コンテナに接続せきることがわかります。ただ、デフォルトのブリッジネットワークにはDNSがないのでIPアドレスを指定しなければ接続できません。

> docker container attach alpine4
/ # ping -c 2 alpine1
PING alpine1 (172.27.0.2): 56 data bytes
64 bytes from 172.27.0.2: seq=0 ttl=64 time=0.695 ms
64 bytes from 172.27.0.2: seq=1 ttl=64 time=0.126 ms

--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.126/0.410/0.695 ms
/ # ping -c 2 alpine2
PING alpine2 (172.27.0.3): 56 data bytes
64 bytes from 172.27.0.3: seq=0 ttl=64 time=0.322 ms
64 bytes from 172.27.0.3: seq=1 ttl=64 time=0.131 ms

--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.131/0.226/0.322 ms
/ # ping -c 2 alpine3
ping: bad address 'alpine3'
/ # ping -c 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.341 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.346 ms

--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.341/0.343/0.346 ms

最後に、どのコンテナからも外部のネットワークと通信できることを確認してみます。

> docker container attach alpine4
/ # ping -c 2 google.com
PING google.com (172.217.25.78): 56 data bytes
64 bytes from 172.217.25.78: seq=0 ttl=37 time=59.183 ms
64 bytes from 172.217.25.78: seq=1 ttl=37 time=69.268 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 59.183/64.225/69.268 ms
/ # read escape sequence
bookstore@ [/Users/bookstore] %
> docker container attach alpine3
/ # ping -c 2 google.com
PING google.com (172.217.25.78): 56 data bytes
64 bytes from 172.217.25.78: seq=0 ttl=37 time=33.973 ms
64 bytes from 172.217.25.78: seq=1 ttl=37 time=30.096 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 30.096/32.034/33.973 ms
/ # read escape sequence
bookstore@ [/Users/bookstore] %
> docker container attach alpine1
/ # ping -c 2 google.com
PING google.com (172.217.26.46): 56 data bytes
64 bytes from 172.217.26.46: seq=0 ttl=37 time=18.858 ms
64 bytes from 172.217.26.46: seq=1 ttl=37 time=35.251 ms

--- google.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 18.858/27.054/35.251 ms

使用させていただいたアイコンについて

Shipping Container icon icon by Icons8