Docker コンテナ・ネットワークの理解¶
ウェブ・アプリケーションの構築は、安全についての考慮が必要であり、そのために Docker ネットワーク機能を使います。ネットワークとは、定義上、コンテナのために完全な分離(isolation)を提供するものです。そして、アプリケーションの実行にあたり、ネットワーク管理は重要であることを意味します。Docker コンテナ・ネットワークは、これらを管理するものです。
このセクションでは、Docker Engine ドライバ固有の標準ネットワーク機能について、その概要を扱います。ここでは標準のネットワーク・タイプについてと、どのようにして自分自身でユーザ定義ネットワークを使うのかを説明します。また、単一ホストまたはクラスタ上をまたがるホストにネットワークを作成するために必要なリソースについても説明します。
デフォルト・ネットワーク¶
Docker をインストールすると、自動的に3つのネットワークを作成します。ネットワーク一覧を表示するには docker network ls
コマンドを使います。
$ docker network ls
NETWORK ID NAME DRIVER
7fca4eb8c647 bridge bridge
9f904ee27bf5 none null
cf03ee007fb4 host host
これまで、3つのネットワークが Docker の一部として実装されています。コンテナを実行するネットワークを指定したいときは、 -net
フラグを使うことができました。これらの3つのネットワークは、まだ今も利用可能です。
Docker をインストールした全ての環境には、 docker0
と表示される bridge
ネットワークが現れます。オプションで docker run --net=<ネットワーク名>
を指定しない限り、Docker デーモンはデフォルトでこのネットワークにコンテナを接続します。ホスト上で ifconfig
コマンドを使うことで、ホストネットワーク上のスタックの一部として、このブリッジを見ることができます。
ubuntu@ip-172-31-36-118:~$ ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:17 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:1100 (1.1 KB) TX bytes:648 (648.0 B)
ネットワーク層に何も追加しない none
ネットワークをコンテナを追加したとします。そのコンテナはネットワーク・インターフェースが欠如しています。コンテナに接続(アタッチ)すると、次のようにスタックが表示されます。
ubuntu@ip-172-31-36-118:~$ docker attach nonenetcontainer
/ # cat /etc/hosts
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
/ # ifconfig
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)
/ #
注釈
コンテナから離れても実行したままにするには、 CTRL-p CTRL-q
を押します。
ホスト・ネットワーク・スタック上のコンテナに host
ネットワークを追加したとします。コンテナ内のネットワーク設定が、ホスト上と同じであるように見えるでしょう。
bridge
ネットワーク使用時をのぞき、これらデフォルト・ネットワークと実際に通信する必要はありません。このように一覧を表示したり調べたりしても、これらを削除できません。これらは Docker のインストールに必要とされているためです。しかしながら、自分自身でユーザ定義ネットワークを追加することができ、また、必要が無いものを削除できます。自分自身のネットワークについて学ぶ前に、デフォルトのネットワークについて少しだけ見ておきましょう。
デフォルトのブリッジ・ネットワーク詳細¶
Docker ホスト上の全てのデフォルト・ネットワーク・ブリッジを表示するには、docker network inspect を使います。
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.1/16",
"Gateway": "172.17.0.1"
}
]
},
"Containers": {},
"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": "9001"
}
}
]
Engine は自動的にネットワーク上に Subnet
と Gateway
を作成します。 docker run
コマンドは新しいコンテナにたいして自動的にこのネットワークを割り当てます。
$ docker run -itd --name=container1 busybox
3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c
$ docker run -itd --name=container2 busybox
94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c
2つのコンテナを実行してから、再びこのブリッジ・ネットワークを参照し、直近のコンテナのネットワークがどのようになっているか見てみましょう。コンテナの ID が表示されるようになります。
$ docker network inspect bridge
{[
{
"Name": "bridge",
"Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.1/16",
"Gateway": "172.17.0.1"
}
]
},
"Containers": {
"3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
"EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c": {
"EndpointID": "b047d090f446ac49747d3c37d63e4307be745876db7f0ceef7b311cbba615f48",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/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": "9001"
}
}
]
上の docker network inspect
コマンドは、接続しているコンテナと特定のネットワーク上にある各々のネットワークを全て表示します。デフォルト・ネットワークのコンテナは、IP アドレスを使って相互に通信できます。デフォルトのネットワーク・ブリッジ上では、Docker は自動的なサービス・ディスカバリをサポートしていません。このデフォルト・ブリッジ・ネットワーク上でコンテナ名を使って通信をしたい場合、コンテナ間の接続にはレガシー(訳者注:古い)の docker run --link
オプションを使う必要があります。
実行しているコンテナに attach
することにより、設定を調査できます。
$ docker attach container1
/ # ifconfig
ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:16 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:1296 (1.2 KiB) 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)
この bridge
ネットワークにおけるコンテナの接続性をテストするため、3秒間 ping
を実行します。
/ # ping -w3 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.096 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.074 ms
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.074/0.083/0.096 ms
最後に cat
コマンドを使い、 container1
のネットワーク設定を確認します。
/ # cat /etc/hosts
172.17.0.2 3386a527aa08
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
container1
からデタッチするには、 CTRL-p CTRL-q
を使って離れます。それから container2
にアタッチし、3つのコマンドを繰り返します。
$ 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:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1166 (1.1 KiB) TX bytes:1026 (1.0 KiB)
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 -w3 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.067 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
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.067/0.071/0.075 ms
/ # cat /etc/hosts
172.17.0.3 94447ca47985
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
デフォルトの docker0
ブリッジ・ネットワークは、ポート・マッピングの使用と、 docker run --link
によって docker0
ネットワーク上にあるコンテナ間の通信を可能とするものです。これらの技術はセットアップが面倒であり、間違いしがちです。この技術はまだ利用可能ですが、これらを使わず、その代わりに自分自身でブリッジ・ネットワークを定義するほうが望ましいです。
ユーザ定義ネットワーク¶
コンテナのより優れた分離のために、自分自身でユーザ定義ネットワーク(user-defined networks)を作成できます。Docker はこれらネットワークを作成するための、複数の ネットワーク・ドライバ を標準提供しています。新しい ブリッジ・ネットワーク や オーバレイ・ネットワーク を作成できます。また、ネットワーク・プラグイン や リモート・ネットワーク を書くことで、自分自身でも定義できます。
ネットワークは複数作成できます。コンテナを1つ以上のネットワークに追加できます。コンテナの通信はネットワーク内だけでなく、ネットワークを交差できます。コンテナが2つのネットワークにアタッチされている場合、どちらのネットワークに対しても通信可能です。
次のいくつかのセクションでは、各 Docker 内蔵ネットワーク・ドライバに関するより詳細を扱います。
ブリッジ・ネットワーク¶
最も簡単なユーザ定義ネットワークは、 bridge
ネットワークの作成です。このネットワークは過去の docker0
ネットワークと似ています。いくつかの新機能が追加されていますが、古い機能のいくつかは利用できません。
$ docker network create --driver bridge isolated_nw
1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1/16"
}
]
},
"Containers": {},
"Options": {}
}
]
$ docker network ls
NETWORK ID NAME DRIVER
9f904ee27bf5 none null
cf03ee007fb4 host host
7fca4eb8c647 bridge bridge
c5ee82f76de3 isolated_nw bridge
ネットワークを作成したら、接続のために、コンテナ起動時に docker run --net=<ネットワーク名>
オプションを使います。
$ docker run --net=isolated_nw -itd --name=container3 busybox
885b7b4f792bae534416c95caa35ba272f201fa181e18e59beba0c80d7d77c1d
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"885b7b4f792bae534416c95caa35ba272f201fa181e18e59beba0c80d7d77c1d": {
"EndpointID": "514e1b419074397ea92bcfaa6698d17feb62db49d1320a27393b853ec65319c3",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
}
},
"Options": {}
}
]
このネットワークの中で起動したコンテナは、Docker ホスト上の他のコンテナとは分離されています。ネットワーク内の各コンテナは速やかに通信が可能です。しかし、コンテナ自身が含まれるネットワークは外部のネットワークと分離されています。
ユーザ定義ブリッジ・ネットワークの内部では、リンク機能はサポートされません。ですが、このネットワーク上にあるコンテナのポートは公開可能です。外側のネットワークを利用するときに、一部としての bridge
ネットワーク作成が役立つでしょう。
ブリッジ・ネットワークは、単一ホスト上で比較的小さなネットワークの実行時に使いやすいです。それだけでなく、とりわけ大きなネットワークでは overlay
ネットワークも作成できます
オーバレイ・ネットワーク¶
Docker の overlay
(オーバレイ)ネットワーク・ドライバは、複数ホストのネットワーキングにネイティブに対応する革新的なものです。このサポートは libnetwork
、 VXLAN を基盤とした内蔵オーバレイ・ネットワーク・ドライバ、Docker の libkv
ライブラリによる成果です。
overlay
ネットワークはキーバリュー・ストア・サービスを必要とします。現時点で Docker の libkv
がサポートしているのは、Consul、Etcd、Zookeeper(分散ストア)です。ネットワークを作成する前に、キーバリュー・ストア・サービスを選び、設定する必要があります。そして、Docker ホストによって、ネットワークとサービスが通信できるようにするでしょう。
ネットワークの各ホストは、それぞれで Docker エンジンを動かす必要があります。最も簡単なのは Docker Machine を使ってホストをプロビジョンする方法です。
ホスト間で以下のポートをオープンにすべきです。
プロトコル | Port | 説明 |
---|---|---|
udp | 4789 | データ用 (VXLAN) |
tcp/udp | 7946 | 管理用 |
使用するキーバリュー・ストアによっては、追加ポートが必要になる場合があります。各ベンダーのドキュメントを確認氏、必要なポートを開いてください。
複数のマシンをプロビジョンしたあとは、Docker Swarm を使って Swarm とディスカバリ・サービスを同様に迅速に入れられます。
オーバレイ・ネットワークを作成するには、各々の Docker Engine 上の daemon
のオプションで、 overlay
ネットワークを設定します。そこには2つの設定オプションがあります:
オプション | 説明 |
---|---|
--cluster-store=PROVIDER://URL |
キーバリュー・サービスの場所を指定 |
–cluster-advertise=HOST_IP|HOST_IFACE:PORT |
クラスタ用に使うホストのインターフェース用 IP アドレス |
--cluster-store-opt=KVSのオプション |
TLS 証明書やディスカバリ間隔の調整のようなオプション。 |
overlay
ネットワークを Swarm のマシン上に作成します。
$ docker network create --driver overlay my-multi-host-network
この結果、複数のホストをまたぐ1つのネットワークができます。 overlay
ネットワークはコンテナに対して、完全なる分離機能を提供します。
以後、各ホスト上でコンテナ起動時にこのネットワーク名を指定します。
$ docker run -itd --net=my-multi-host-network busybox
接続したあと、ネットワーク内の各コンテナ全てにアクセス可能となります。このとき、コンテナがどこのホスト上で起動しているか気にする必要はありません。
自分自身で試したい場合は、こちらの overlay 導入ガイド をご覧ください。
カスタム・ネットワーク・プラグイン¶
必要があれば、自分自身でネットワーク・ドライバ・プラグインを書けます。ネットワーク・ドライバ・プラグインは Docker のプラグイン基盤を使います。この基盤を使い、Docker デーモン
が動作する同じ Docker ホストでプラグインをプロセスとして実行します。
ネットワーク・プラグインは、他のプラグインと同様、いくつかの制約やインストール時のルールがあります。全てのプラグインはプラグイン API を利用します。これらはインストール、開始、停止、有効化といったライフサイクル全般に亘ります。
カスタム・ネットワーク・ドライバを作成してインストールした後は、内蔵ネットワーク・ドライバと同じように扱えます。例:
$ docker network create --driver weave mynet
内部を確認できますし、さらにコンテナを追加したり、いろいろできます。もちろん、プラグイン毎に異なった技術やフレームワークを使うこともあるでしょう。カスタム・ネットワークは Docker の標準ネットワークが持たない機能を実装できます。プラグインの書き方に関する詳細情報は、 Docker 拡張 または ネットワーク・ドライバ・プラグインの書き方 をお読みください。
Docker 内蔵 DNS サーバ¶
Docker デーモンは内蔵 DNS サーバを実行し、ユーザ定義ネットワーク上でコンテナがサービス・ディスカバリを自動的に行えるようにします。コンテナから名前解決のリクエストがあれば、内蔵 DNS サーバを第一に使います。リクエストがあっても内蔵 DNS サーバが名前解決できなければ、外部の DNS サーバにコンテナからのリクエストを手の鮨ます。割り当てできるのはコンテナの作成時だけです。内蔵 DNS サーバが到達可能なのは 127.0.0.11
のみであり、コンテナの resolv.conf
に書かれます。ユーザ定義ネットワーク上の内蔵 DNS サーバに関しては ユーザ定義ネットワーク用の内蔵 DNS サーバ をご覧ください。
リンク機能¶
Docker ネットワーク機能より以前は、Docker リンク機能を使いコンテナをお互いに発見したり、特定のコンテナから別のコンテナに安全に情報を送信できました。Docker ネットワークを導入すると、自動的にコンテナは名前で見つけることができます。しかし、デフォルトの docker0
ブリッジ・ネットワークとユーザ定義ネットワークには違いがあるため、まだリンク機能を使うこともできます。より詳しい情報については、 古いリンク機能 のデフォルト bridge
ネットワークのリンク機能をご覧ください。ユーザ定義ネットワークでリンク機能を使うには ユーザ定義ネットワークでコンテナをリンク をご覧ください。
関連情報¶
参考
- Understand Docker container networks
- https://docs.docker.com/engine/userguide/networking/dockernetworks/