はじめに
Dockerコンテナがどのようにネットワークを構成しているかを確認します。
目的
Dockerを触りながら、コンテナ同士のネットワークを確認する
今回は、下記の操作を行います。
- コンテナのIPアドレスを確認
- コンテナ用の仮想ネットワークを確認
- 仮想ネットワークのファイアウォールを確認
- 新しい仮想ネットワークの作成
- コンテナを新しいネットワークで起動
- コンテナを別のネットワークに接続する
- コンテナのDNSを確認する
環境
- macOS Mojave 10.14.6
- Docker engine 19.03.5
まずはDockerのインストール
コンテナをアレコレしてみる
まずはコンテナを起動
以下のコマンドは、nginxのコンテナを起動します。
-
-p
オプションによって、80:80
のポートを開いています。 -
-d
オプションによって、バックグラウンドでコンテナが起動します。 -
--name
オプションによって、nginx
と名付けました。
docker container run -p 80:80 -d --name nginx nginx
container port
以下のコマンドを実行することで、指定したコンテナのどのポートが通信を受け付けているか確認できます。
docker container port nginx
--format {{.NetworkSettings.IPAddress}}
コンテナのIPアドレスを確認するには、以下のコマンドを実行します。
docker container inspect --format {{.NetworkSettings.IPAddress}} nginx
# 172.17.0.2
172.17.0.2
とIPアドレスが表示されました。
これはどこから来ているのでしょうか。
ホストのIPアドレスとコンテナのIPアドレス
試しに、ホストのIPアドレスを調べてみます。
ifconfig en0
#en0: flags=8888<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
# ether 8a:88:88:54:67:8f
# inet6 fe88::897:4382:278d:2dfa%en0 prefixlen 64 secured scpeid 0x8
# inet 192.168.11.13 netmask 0xffffff00 broadcast 192.168.11.255
# nd6 options=201<PERFORMNUD,DAD>
# media: autoselect
# status: active
どうもホストのIPとは異なるIPアドレスがコンテナに割り当てられているようです。
仮想ネットワーク「ブリッジ」
結論から言うと、コンテナのIPアドレスは
コンテナ用の仮想ネットワークのIPアドレスから割り当てられています。
コンテナが新しく作られると、そのコンテナは「ブリッジ」と呼ばれるデフォルトの仮想ネットワークに紐づけられます。
ブリッジは、ホストOSのイーサネットインターフェースに繋がっているので、コンテナも外との通信ができるようになっています。
先ほどコンテナを起動する際に指定した-p 80:80
は、
ホストOSのポート80番を開き、80番ポートへの通信は全て仮想ネットワーク「ブリッジ」を通じてコンテナに転送されています。
仮想ネットワークのファイアウォール
反対に-p
オプションを指定しなければ、コンテナは外と通信できないことになります。
これは簡易的なファイアウォールであり、
こちらから-p
で通信を許可しない限り、コンテナは基本的にプライベートなものです。
コンテナを追加したら
もし、ここに新しいコンテナを追加するとどうなるでしょうか。
なお今回は、-p
オプションを使用しないでコンテナを起動します。
docker container run -d --name second nginx
最初のnginxコンテナと同じく、ブリッジにコンテナは接続されています。
同じ「ブリッジ」ネットワークにいるので、一つ目のコンテナと二つ目のコンテナは互いに通信が可能です。
しかし、二つ目のコンテナは-p
オプションを使用していないので、ホストOS側ではどのポートも通信を待ち受けていません。
したがって、二つ目のコンテナは外部からは遮断されたコンテナということになります。
- 一つ目の外部と通信できるコンテナはWebサーバーなどに使用できるパブリックなコンテナ
- 二つ目のコンテナはインターネットには繋がっていないプライベートなコンテナなので、DBなどに使えます
network ls
仮想ネットワークを確認するには、以下のコマンドを実行します。
「bridge」ネットワーク、つまりデフォルトのコンテナ用ネットワークが確認できるかと思います。
docker network ls
network inspect
指定したネットワークの状態を確認します。
以下のコマンドはbridge
ネットワークの状態を確認するコマンドです。
docker network inspect bridge
bridgeネットワーク内にどのコンテナが存在しているかも、ここから確認することができます。
$~ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "48a7de8fa4625a82b06468c37a5446a044a",
...
"IPAM": {
...
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
...
"Containers": {
"92827df330b042420f96619ce2476127c9d2c1": {
"Name": "nginx",
...
"IPv4Address": "172.17.0.2/16",
...
},
"c76508a92f8ed89d054b4bbba16e3f64ecb48b": {
"Name": "second",
...
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
また、IPAM(IP address management)
を確認することで、サブネットのデフォルトIPアドレスを確認できます。
ここでは、
"Subnet": "172.17.0.0/16"
となっていますね。
コンテナのIPアドレスは
- 一つ目のコンテナ:
"172.17.0.2/16"
- 二つ目のコンテナ:
"172.17.0.3/16"
となっています。
コンテナのIPが、サブネットのIPアドレスの範囲内にありますので、
ちゃんとサブネット内にコンテナが存在していることがここからも確認できます。
network create
では今度は、デフォルトの「ブリッジ」ではなく自分で仮想ネットワークを作ります。
以下のコマンドを実行することでmynet
という名前の仮想ネットワークを作成できます。
docker network create mynet
--network
--netowork
オプションを使用することで、指定したネットワークでコンテナを起動することができます。
docker container run -d --name proxy --network mynet nginx
network connect
コンテナを別のネットワークに繋げることもできます。
docker network connect 2ed32 92827
-
2ed32
(新しいmynet
ネットワークのID) -
92827
(ブリッジネットワークのnginx
コンテナのID)
ここでは、ブリッジネットワークのnginx
コンテナをmynet
ネットワークに繋げています。
コンテナが移動したわけでははないので、
ブリッジにもnginx
コンテナは繋がっていますし
mynet
にも繋がっている状態になっています。
network disconnect
もちろん、接続を断つコマンドもあります。
が、今回は省略します。
コンテナのDNS
このように、ブリッジをはじめとするコンテナ用サブネットや、コンテナそのものにはIPアドレスが割り当てられていますが、コンテナを運用する上でIPアドレスを使用することは推奨されていません。代わりにコンテナやネットワークにつけた名前を使用します。
なぜなら、コンテナは作ったり、削除したり、移動したりするからです。
また、コンテナを立ち上げる順番なども、運用する環境によって変わってしまうかもしれません。
そうした環境においてはIPアドレスは常に一定ではありません。
しかし、DockerにはDNSが標準で組み込まれていますので、
(これまでも使用してきたように)名前を使用してコンテナやネットワークを指定することができますし、そのほうが安定します。
まとめ
- コンテナのIPアドレスを確認
- コンテナ用の仮想ネットワークを確認
- 仮想ネットワークのファイアウォールを確認
- 新しい仮想ネットワークの作成
- コンテナを新しいネットワークで起動
- コンテナを別のネットワークに接続する
- コンテナのDNSを確認する
上記の内容を、実際に手を動かしながら確認することで、
コンテナがホストOS上に作られた仮想ネットワーク上で動いていることがざっくり分かりました。