この記事は、福岡若手Sier_bc Advent Calendar 2019 の 13 日目の投稿です。
はじめに
Docker を勉強していて、どうも難しく感じてしまうのがコンテナのネットワークについて。
自分の備忘録もかねて徒然なるままに綴ります。
確認用の環境構築
確認用の環境は、Virtual Box で仮想マシンを作成し、その中に Docker の環境を作ります。
以前の自分の投稿で、
ただ、個人的に Virtual Box で仮想マシン作って〜、Nginx インストールして〜
ってのはめんどくさいので Docker でやってしまいます。(ごめんね)
と書いていましたが今回はわざわざ Virtual Box 上に Docker の環境を作ります。
ただ、ここはさすが Docker さん。
簡単に環境を構築できるコマンドが用意されています。
それが、 docker-machine コマンド。
( 「Docker 版の Vagrant 的なやつ」 と言うとイメージがしやすい?? )
やり方は簡単で、Virtual Box と docker-machine コマンドをインストール して以下のコマンドを実行。
docker-machine create nw-vm
これで、Virtual Box 上に Docker の環境が入ったnw-vm
という名前のインスタンスが立ち上がります。
インスタンスの中に入るには、
$ docker-machine ssh nw-vm
( '>')
/) TC (\ Core is distributed with ABSOLUTELY NO WARRANTY.
(/-_--_-\) www.tinycorelinux.net
docker@nw-vm:~$
で中に入れます。
デフォルトのネットワーク
インスタンスの中に入ったら、デフォルトの Docker ネットワークを確認します。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
4a85b1978bc9 bridge bridge local
f06510f48928 host host local
6aa5429b7a4f none null local
Docker をインストールすると必ずこれらのネットワークが作成されます。
bridge network
コンテナを起動する際に特にネットワークを指定しないと bridge
が選択されます。
その詳細を確認します。
( ちなみに、docker で何かの詳細を確認する時はだいたい、docker ~ inspect ~
です。)
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "4a85b1978bc9dfb5f5304686227fd6e4f34d7f0ef4cb567f7fb091211a9feb13",
"Created": "2019-12-12T14:17:10.468964848Z",
"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": {},
"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": {}
}
]
注目すべきは以下です。
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
コンテナは、172.17.0.0/16
のネットワークに所属します。
そして、ゲートウェイの 172.17.0.1
は docker0
インターフェースに接続されています。
インスタンスのネットワークインターフェースを確認します。
$ ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:7C:77:4F:5F
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST MULTICAST MTU:1500 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)
inet addr:172.17.0.1
で、確かに docker0
インターフェースが 172.17.0.1
の IP アドレスが割り当てられていることが確認できました。
コンテナを起動してみる
$ docker run -itd --rm --name=nginx nginx
で起動し、詳細を確認
$ docker inspect nginx
~~~ 省略 ~~~
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "4a85b1978bc9dfb5f5304686227fd6e4f34d7f0ef4cb567f7fb091211a9feb13",
"EndpointID": "a3414897f695a122751cc0e33de651b988a91c3b69b493ad4ad66efab29b41d2",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
~~~ 省略 ~~~
めちゃめちゃ表示される中から下の方の Networks
でコンテナのネットワーク状態を確認できます。
このコンテナには、172.17.0.2
の IP アドレスが割り当てられています。
ネットワークの作成
$ docker network create my-bridge
でユーザ定義のブリッジネットワークを作成することができます。
コンテナをネットワークに接続するためには、
// 起動中のコンテナの場合
docker network connect <ネットワーク名> <コンテナ名>
// 最初からネットワークに接続して起動する場合
docker run --network <ネットワーク名> ~~~
作成した、my-bridge
とデフォルトの bridge
の違いは、コンテナ名で名前解決ができるかどうかです。
ユーザ定義のネットワークであれば、コンテナ名で名前解決ができるため、
同じネットワークに所属するコンテナ同士であれば、コンテナ名で通信することができます。
host network
コンテナがこのネットワークに所属した状態で起動すると、コンテナはホストマシンのネットワークインターフェースと共有された状態になります。
例えば、Nginx のサーバを起動した場合、外部からコンテナの 80 番ポートにアクセスするためには -p
オプションでポートフォワードを設定する必要があります。
しかし、host ネットワークであれば Nginx を起動したらホストマシンの 80 番ポートがそのままコンテナの 80 番ポートに流れて行きます。
docker-machine
コマンドで起動したインスタンスの IP アドレスは、
$ docker-machine ip nw-vm
192.168.99.115
で確認することができます。
この状態で、host ネットワークに所属した Nginx コンテナを起動します。
$ docker run -itd --name=nginx2 --rm --network=host nginx
これで、ブラウザから先ほど確認した http://192.168.99.115 にアクセスすると Nginx デフォルトページが表示されるはずです。
none network
コンテナがこのネットワークに所属した状態で起動すると、このコンテナは ループバックインターフェースしか持たない 状態になります。
さいごに
立ち上げたインスタンスの停止は以下のコマンドでできます。
$ docker-machine stop nw-vm
次はマルチホスト上でのコンテナ間通信について書こうと思います。
ちなみに
docker-machine コマンドは有能なやつで、AWS の EC2 上に Docker ホストを構築できちゃったりもします。
詳しくは自分で調べてください。()