network コマンドを使う

この記事ではネットワーク・サブコマンドの例を扱います。このサブコマンドはDocket ネットワークを相互に扱い、コンテナをネットワークに配置します。コマンドは Docker エンジン CLI を通して利用可能です。コマンドとは以下の通りです。

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

必要としなくても、このセクションの例に取り組む前に、 Docker ネットワークの理解 を読むのは良い考えです。例では bridge ネットワークを使用するため、すぐに試せられます。 overlay ネットワークを試したいのであれば、 マルチホスト・ネットワーキングを始める をご覧ください。

ネットワークの作成

Docker エンジンをインストールすると、Docker エンジンは自動的に bridge ネットワークを作成します。このネットワークは、エンジンが従来使ってきた docker0 ブリッジに相当します。このネットワークに対して付け加えておくと、自分自身で bridge (ブリッジ)や overlay (オーバレイ)ネットワークを作成可能です。

bridge ネットワークは Docker エンジンの実行ホスト環境上に存在します。 overlay ネットワークは、複数のホスト上で動くエンジンをまたがっています。 docker network create を実行する時、ネットワーク名だけ指定すると、ブリッジ・ネットワークを作成します。

$ 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": {}
    }
]

ブリッジ・ネットワークとは異なり、 overlay ネットワークの場合は、作成前に事前準備がいくつか必要です。事前準備とは、次の通りです。

  • キーバリュー・ストアへのアクセス。エンジンがサポートするキーバリュー・ストアは Consul、Etcd、ZooKeeper(分散ストア)です。
  • ホストのクラスタが、キーバリュー・ストアへ接続できること。
  • 各ホスト上のエンジン daemon に、 Swarm クラスタとしての適切な設定をすること。

overlay ネットワークがサポートする docker daemon のオプションは、次の通りです。

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

また、必要がなくても Docker Swarm をクラスタ管理用にインストールするのも良い考えでしょう。Swarm はクラスタの設定を手助けするために、洗練されたディスカバリとサーバ管理機能を持っています。

デフォルトではネットワーク作成時、エンジンはサブネットが重複しないネットワークを作成します。このデフォルトの挙動は変更できます。特定のサブネットワークを直接指定するには --subnet オプションを使います。 bridge ネットワーク上では1つだけサブネットを作成できます。 overlay ネットワークでは、複数のサブネットをサポートしています。

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

サブネットワークが重複しないように注意してください。重複すると、ネットワーク作成が失敗し、エンジンはエラーを返します。

コンテナに接続

コンテナは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": {}
    }
]

エンジンが自動的に container2 に IP アドレスを割り当てているのが分かります。もしもネットワーク作成時に --subnetwork を指定しているのであれば、そのネットワーク体系から割り当てられます。次は3つめのコンテナを起動し、ネットワークに接続するために、 docker run コマンドに --net オプションを使います。

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

次は、 container3 に対するネットワークのリソースを調査します。

$ 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 をインストール済みであれば、次のように表示を分かりやすくできるでしょう。

$ 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 ネットワークは後から自分で接続したものです。

Docker のネットワーク

container3 の場合、 docker runisolated_nw に接続したので、このコンテナは bridge に接続していません。

docker attach コマンドで実行中の container2 に接続詞、ネットワーク・スタックを確認しましょう。

$ docker attach container2

コンテナのネットワーク・スタックを確認すると、2つのイーサネット・インターフェースが見えます。1つはデフォルトの bridge ネットワークであり、もう1つは 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 ネットワーク機能が /etc/hosts を更新し、適切な名前解決を行います。 container2 の内部では、 container3 に対して名前で ping できるでしょう。

/ # 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

デフォルトのブリッジ・ネットワークを使っている場合、この名前解決機能を利用できません。 containe2container1 は、どちらもデフォルトのブリッジ・ネットワークに接続しています。このデフォルトのネットワーク上では、Docker は自動サービス・ディスカバリをサポートしません。そのため、 container1 に対して名前で ping をしても、 /etc/hosts ファイルには記述がないため失敗するでしょう。

/ # ping -w 4 container1
ping: bad address 'container1'

container1 の IP アドレスであれば、次のように処理できます。

/ # 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 アドレスだけでなく、名前で通信できるようになります。

container2 からデタッチして離れるには、 CTRL-p CTRL-q を実行します。

この例では、 container2 は両方のネットワークにアタッチしているため、 container1container3 の両方と通信できます。しかし、 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

コンテナのネットワークに接続するとき、コンテナは実行中の必要があります。コンテナを停止して確認( inspect )すると、ネットワークには所属したままですが、コンテナの情報が見えなくなるでしょう。 docker network inspect コマンドは、実行中のコンテナのみ表示します。

コンテナの切断

コンテナをネットワークから切断するには docker network disconnect コマンドを使います。

$ docker network disconnect isolated_nw container2

docker inspect --format='{{json .NetworkSettings.Networks}}'  container2 | python -m json.tool
{
    "bridge": {
        "EndpointID": "9e4575f7f61c0f9d69317b7a4b92eefc133347836dd83ef65deffa16b9985dc0",
        "Gateway": "172.17.0.1",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "172.17.0.3",
        "IPPrefixLen": 16,
        "IPv6Gateway": "",
        "MacAddress": "02:42:ac:11:00:03"
    }
}


$ docker network inspect isolated_nw
[[
    {
        "Name": "isolated_nw",
        "Id": "f836c8deb6282ee614eade9d2f42d590e603d0b1efa0d99bd88b88c503e6ba7a",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {}
            ]
        },
        "Containers": {
            "c282ca437ee7e926a7303a64fc04109740208d2c20e442366139322211a6481c": {
                "EndpointID": "e5d077f9712a69c6929fdd890df5e7c1c649771a50df5b422f7e68f0ae61e847",
                "MacAddress": "02:42:ac:15:00:03",
                "IPv4Address": "172.21.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {}
    }
]

コンテナがネットワークから切断されると、対象ネットワーク上で接続していたコンテナと通信できなくなります。この例では、 container2isolated_nw ネットワーク上の container3 とは通信できなくなります。

$ docker attach container2

/ # 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)

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)

/ # ping container3
PING container3 (172.20.0.1): 56 data bytes
^C
--- container3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

container2 は、ブリッジ・ネットワークに対する接続性をまだ維持しています。

/ # ping container1
PING container1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.119 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.174 ms
^C
--- container1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.119/0.146/0.174 ms
/ #

ネットワークの削除

ネットワーク上の全てのコンテナが停止するか切断すると、ネットワークを削除できます。

$ docker network disconnect isolated_nw container3
docker network inspect isolated_nw
[
    {
        "Name": "isolated_nw",
        "Id": "f836c8deb6282ee614eade9d2f42d590e603d0b1efa0d99bd88b88c503e6ba7a",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {}
            ]
        },
        "Containers": {},
        "Options": {}
    }
]

$ docker network rm isolated_nw

すべてのネットワーク情報を確認すると、 isolated_nw が削除されています。

$ docker network ls
NETWORK ID          NAME                DRIVER
72314fa53006        host                host
f7ab26d71dbd        bridge              bridge
0f32e83e61ac        none                null