关于Docker的网络
这篇文章是福冈年轻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
$ 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 が選択されます。
その詳細を確認します。
( ちなみに、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接口被分配了IP地址172.17.0.1。
我试着启动容器。
$ 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 选项中,从大量显示结果中确认容器的网络状态。
该容器被分配了一个 IP 地址为 172.17.0.2。
创建网络
$ docker network create my-bridge
您可以创建用户定义的桥接网络。
要将容器连接到网络,
// 起動中のコンテナの場合
docker network connect <ネットワーク名> <コンテナ名>
// 最初からネットワークに接続して起動する場合
docker run --network <ネットワーク名> ~~~
my-bridge 和默认桥接的区别在于是否可以通过容器名称进行名称解析。
如果是用户定义的网络,则可以通过容器名称进行名称解析,
这意味着属于同一网络的容器之间可以通过容器名称进行通信。
主机网络
当容器在此网络中启动时,容器将处于与主机的网络接口共享的状态。
例如,如果启动了Nginx服务器,则需要使用-p选项设置端口转发才能从外部访问容器的80号端口。
然而,如果使用主机网络,则一旦启动了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
无网络
当容器在加入此网络后启动,该容器将变为只拥有环回接口的状态。
最后
您可以使用以下命令停止已启动的实例。
$ docker-machine stop nw-vm
接下来,我打算写关于在多主机上的容器间通信。
顺便提一下
docker-machine这个命令是一个强大的工具,可以在AWS的EC2上建立Docker主机。请自行查找更详细的资料。