一、Docker网络管理方面的命令 

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

二、创建网络

在创建网络时,Docker默认会为创建的网络创建子网,你可以通过--subnet标识定义自己的子网。在创建bridge网络时只能指定一个子网,创建overlay网络时 可以指定多个子网。此外,还可以同时指定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

必须确保你指定的子网是没有重叠的,否则Docker会返回错误。

二、将容器连接到网络

你可以使用docker network connect命令将容器连接到一个或多个自定义网络,连接到同一个网络的容器之间可以通过IP或名字进行通信。 

下面的例子创建了两个容器,默认都连接到了docker0网络:

$ docker run -itd --name=container1 busybox
18c062ef45ac0c026ee48a83afa39d25635ee5f02b58de4abc8f467bcaa28731

$ docker run -itd --name=container2 busybox
498eaaaf328e1018042c04b2de04036fc04719a6e39a097a4f4866043a2c2152

然后创建一个用于测试的bridge网络:

$ docker network create -d bridge isolated_nw
f836c8deb6282ee614eade9d2f42d590e603d0b1efa0d99bd88b88c503e6ba7a

然后将container2连接到isolated_nw上,此时isolated_nw网络上就有了一个容器:

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

可以看到Docker为容器分配了IP,如果你在创建自定义网络时制指定了--subnet,则IP地址就从你指定的范围内选择一个可用的分配给容器。 

然后,启动第三个容器,在docker run命令中通过--net指定isolated_nw:

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

此时查看container2中的网络,可以看到如下信息:

$ 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连接到了两个不同网络,每个网络都为它分配了IP地址。 

目前容器与网络之间的关系如下图(图片来自Docker官网Docker docs): 


Docker 网络相关命令 (二)_自定义

在启动container3时,通过--net指定了网络isolated_nw,那么container3就不会连接到docker0上。

此时他通过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)

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)

即container2有两张网卡,一个连接到docker0,另一个连接到isolated_nw。 

此外,container2容器的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

可以看到,将容器连入自定义网络时,Docker会将这个网络中其他容器的IP和对应的容器名称写入hosts文件,而连到默认的docker0网络时则不会。此例中,container3的IP和名字被写入了container2的hosts文件,而container1的相关信息没有写入container2的hosts文件。这也是连入自定义网络的容器之间可以通过名字通信,而连到docker0网络的容器不能通过容器名字通信的原因。

最后,需要指出的是,要将一个容器连入网络,容器必须处于运行状态(running)。不仅如此,如果一个容器停止了(stopped),在inspect这个网络时将看不到这个容器。也就是说,docker network inspect命令仅能看到正在运行的容器。

断开容器与网络的连接

断开容器与网络的连接使用docker network disconnect命令。

$ docker network disconnect isolated_nw container2

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

一旦断开之后,容器就不能和那个网络中的容器通信了。

移除网络

移除自定义网络的命令是docker network rm。移除网络前必须确保网络上没有连接容器或连接的容器都已停止运行。

$ docker network rm isolated_nw

通过docker network ls查看是否被删除:

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

isolated_nw已被删除。