[翻訳] Work with network commands


Work with network commandsの翻訳です。
(disconnect / remove はさほどではなかったので省略しています)

Work with network commands

本稿は Docker とやり取りをして network や container を操作する network サブコマンドの例を示します。
コマンドは Docker Engine CLI で利用可能です。

  • docker network create
  • docker network connect
  • docker network ls
  • docker network rm
  • docker network disconnect
  • docker network inspect

やりたいことが明確で無いのであれば、本セクションの例を試す前に Understanding Docker network を読むのがおすすめです。
bridge ネットワークに関しての例で、すぐに試すことができます。
overlay ネットワークの実験をしてみたいのであれば、 Getting started with multi-host networks を読んでみてください。

Create networks

Docker Engine は Engine がインストールされた時に自動的に1つ bridge ネットワークを作成します。
このネットワークは 過去 docker0 として利用してきたネットワークに対応します。
このネットワークに加えて、あなた自身の bridge または overlay ネットワークを作成位することができます。

bridge ネットワークは、稼働している Docker Engine のインスタンスの1つに1つ存在しています。
overlay ネットワークは複数のホストに渡り、それぞれの Engine で稼働します。
もし、 docker network create を実行し、ネットワーク名を与えれば、あなたのための bridge network を作成することができます。

$ docker network create simple-network
de792b8258895cf5dc3b43835e9d61a9803500b991654dacb1f4f0546b1c88f8
$ docker network inspect simple-network
[
    {
        "Name": "simple-network",
        "Id": "de792b8258895cf5dc3b43835e9d61a9803500b991654dacb1f4f0546b1c88f8",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {}
            ]
        },
        "Containers": {},
        "Options": {}
    }
]

bridge ネットワークではなく、 overlay ネットワークは作成前にいくつかの事前条件が必要になります。

  • key-value ストアにアクセスできること. Engine は Consul 、 Etcd および ZooKeeper (Distributed store) をサポートしています
  • ホストのクラスタが key-value ストアに接続されていること
  • 適切に設定された daemon Engine が swarm のホストに存在していること

docker daemon のオプションは overlay ネットワークをサポートしています。

  • --cluster-store
  • --cluster-store-opt
  • --cluster-advertise

特に要件がなければ、 Docker Swarm をインストールして、クラスタを管理するのがおすすめです。
Swarm は洗練されたディスカバリとサーバ管理を提供しています。

ネットワークを作成するときに、 Engine はオーバラップされていない subnetwork をデフォルトでネットワークに対して作成します。
このデフォルトを上書きし、--subnet を利用することで直接にサブネットワー指定することができます。
bridge ネットワークの場合は、たった一つのサブネットだけが作成可能です。
overlay ネットワークは複数の subnet をサポートしています。

--subnetwork オプションに加え、 --gateway--ip-range--aux-address オプションを指定することができます。

$ docker network create -d overlay
  --subnet=192.168.0.0/16 --subnet=192.170.0.0/16
  --gateway=192.168.0.100 --gateway=192.170.0.100
  --ip-range=192.168.1.0/24
  --aux-address a=192.168.1.5 --aux-address b=192.168.1.6
  --aux-address a=192.170.1.5 --aux-address b=192.170.1.6
  my-multihost-network

サブネットワークがオーバラップされないことを確認してください。その場合は、ネットワークは作成に失敗し、 Engine はエラーを返します。

Connect containers

コンテナを動的に1つまたはそれ以上のネットワークに属させることができます。これらのネットワークは同一でも異なっているネットワークドライバでも構いません。
一旦属させてしまえば、コンテナはその他のコンテナ IP アドレスまたは名前を利用してコミュニケーションすることができるようになります。

overlay ネットワークまたはマルチホストをサポートするカスタムプラグインであったとしても、同一のマルチホストネットワークに属しているコンテナはたとえ異なるホストで立ち上げられたとしても、コミュニケーションすることができます。

2つのコンテナを作ってみます。

$ docker run -itd --name=container1 busybox
18c062ef45ac0c026ee48a83afa39d25635ee5f02b58de4abc8f467bcaa28731

$ docker run -itd --name=container2 busybox
498eaaaf328e1018042c04b2de04036fc04719a6e39a097a4f4866043a2c2152

それから、独立した bridge ネットワークをテスト用に作ってみます

$ docker network create -d bridge isolated_nw
f836c8deb6282ee614eade9d2f42d590e603d0b1efa0d99bd88b88c503e6ba7a

container2 をこのネットワークに所属させ、その後 inspect でこのネットワークのコネクションを確認します。

$ docker network connect isolated_nw container2
$ docker network inspect isolated_nw
[[
    {
        "Name": "isolated_nw",
        "Id": "f836c8deb6282ee614eade9d2f42d590e603d0b1efa0d99bd88b88c503e6ba7a",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {}
            ]
        },
        "Containers": {
            "498eaaaf328e1018042c04b2de04036fc04719a6e39a097a4f4866043a2c2152": {
                "EndpointID": "0e24479cfaafb029104999b4e120858a07b19b1b6d956ae56811033e45d68ad9",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "172.21.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {}
    }
]

Engine が自動的に IP アドレスが container2 に振っていることが確認できるはずです。
もし、ネットワーク作成時に --subnetwork を指定しているならば、ネットワークがそのアドレスを使っているはずです。
さて、3つ目のコンテナを立ち上げ、ネットワークに属させてみましょう。 docker run の時に --net コマンドを使って、起動時に。

$ docker run --net=isolated_nw -itd --name=container3 busybox
c282ca437ee7e926a7303a64fc04109740208d2c20e442366139322211a6481c

container3 のネットワークリソースを(inspect で)見てみましょう

$ docker inspect --format='{{json .NetworkSettings.Networks}}'  container3
{"isolated_nw":{"EndpointID":"e5d077f9712a69c6929fdd890df5e7c1c649771a50df5b422f7e68f0ae61e847","Gateway":"172.21.0.1","IPAddress":"172.21.0.3","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:15:00:03"}}

このコマンドを container2 に対して繰り返してみてください。 Python がインストールされているのであれば、整形してみることができます(※訳注: jq使えばいいです)

$ docker inspect --format='{{json .NetworkSettings.Networks}}'  container2 | python -m json.tool
{
    "bridge": {
        "EndpointID": "281b5ead415cf48a6a84fd1a6504342c76e9091fe09b4fdbcc4a01c30b0d3c5b",
        "Gateway": "172.17.0.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.17.0.3",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "MacAddress": "02:42:ac:11:00:03"
    },
    "isolated_nw": {
        "EndpointID": "0e24479cfaafb029104999b4e120858a07b19b1b6d956ae56811033e45d68ad9",
        "Gateway": "172.21.0.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.21.0.2",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "MacAddress": "02:42:ac:15:00:02"
    }
}

container2 が2つのネットワークに属していることが見て取れるはずです。起動した時にデフォルトで所属していた bridge ネットワークとその後、結びつけた isolated_nw です。

!

container3 の場合には、docker run を通して結びつけた isolated_nw だけで、 bridge には結び付けられていません。

docker attach コマンドを利用して、稼働中の container2 に接続し、ネットワークスタックを調べてみましょう。

$ docker attach container2

コンテナのネットワークスタックを見てみると、 Ethernet interface が2つあるはずです。1つはデフォルトのbridgeネッワーク、もう一つは isolated_nw ネットワークです。

/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03  
          inet addr:172.17.0.3  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe11:3/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:8 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:648 (648.0 B)  TX bytes:648 (648.0 B)

eth1      Link encap:Ethernet  HWaddr 02:42:AC:15:00:02  
          inet addr:172.21.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:acff:fe15:2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 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:648 (648.0 B)  TX bytes:648 (648.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)

/etc/hosts も表示してみます。

/ # cat /etc/hosts
172.17.0.3  498eaaaf328e
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.21.0.3  container3
172.21.0.3  container3.isolated_nw

ユーザが定義した isolated_nw 上で、 Docker network の機能により /etc/hosts が適切に名前解決ができるように更新されています。
container2 の中から、 ping container3 を名前で実行することが可能です。

/ # ping -w 4 container3
PING container3 (172.21.0.3): 56 data bytes
64 bytes from 172.21.0.3: seq=0 ttl=64 time=0.070 ms
64 bytes from 172.21.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.21.0.3: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.21.0.3: seq=3 ttl=64 time=0.097 ms

--- container3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.070/0.081/0.097 ms

デフォルトの bridge ネットワークの場合はこうではありません。 container2container1 はデフォルトの bridge ネットワークに属しています。 Docker は自動的にサービスディスカバリをこのネットワークに対しては行えません。
このため、 container1 への ping は /etc/hosts ファイルをベースにしてくれると期待して名前で行うと失敗します。

/ # ping -w 4 container1
ping: bad address 'container1'
A ping using the container1 IP address does succeed though:

/ # ping -w 4 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.095 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.075 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.072 ms
64 bytes from 172.17.0.2: seq=3 ttl=64 time=0.101 ms

--- 172.17.0.2 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.072/0.085/0.101 ms

もし、 container1container2 に結びつけたければ、 docker run --link コマンドで行い、2つのコンテナが IP と同じように名前で疎通できるようにする必要があります。

CTRL-p CTRL-q を利用して、稼働させたまま container2 から切り離します。

この例では、 container2 が両方のネットワークに結び付けられており、 container1 および container3 とコミュニケートしていました。
しかし、 container3container1 は同じネットワークには属しておらず、それゆえコミュニケーションができません。
では、 container3 にアタッチし、 container1 に IP アドレスで ping してみましょう。

$ docker attach container3
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
^C
--- 172.17.0.2 ping statistics ---
10 packets transmitted, 0 packets received, 100% packet loss

コンテナをネットワークに所属させるために、コンテナは稼働していなければなりません。
コンテナを止め、コンテナが所属しているネットワークを調べると、コンテナを発見できないでしょう。
docker network inspect コマンドは起動しているコンテナだけを表示するからです。