1. Docker默认自动创建的网络
当安装完Docker时,Docker默认自动创建了三个网络:bridege, none和host. 使用docker network list命令可以查看。
$ docker network ls
NETWORK ID NAME DRIVER
507d17743c82 bridge bridge
14984b1fcc40 host host
0aba874b7156 none null
使用Docker运行容器时,可以用--net来指定容器运行时所在的网络。例如:
$ docker run --net=host -itd --name=container busybox
1.1 Docker的bridge网络
使用ifconfig命令,可以看到多出了一个docker0:
$ ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:bf:c2:8c:9a
inet addr:172.17.0.1 Bcast:0.0.0.0 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)
docker0是Docker在安装时创建的bridge网络。如果运行容器时没有使用--net,则容器默认运行在bridge网络。使用docker network inspect命令查看bridge的详细信息:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "507d17743c82d550f4c367f42f17f210f08f9b679191a3fb610fed33dfe525e1",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Internal": 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": {}
}
]
从上面的信息可以看到,Docker引擎在docker0上所创建的bridge子网为172.17.0.0/16,目前该网络内还没有容器在运行。现在使用docker run命令增加两个容器
$ docker run -itd --name=container1 busybox
de95bdb8761f646a3f8423724f944f420e332fa3070bae1ff3fec127411e015e
$ docker run -itd --name=container2 busybox
c5bdfc331017107be4ae1bdfff12e531b3eaa3424852c4404a301b1f1c28f31b
再次用docker network inspect命令查看bridge的详细信息:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "507d17743c82d550f4c367f42f17f210f08f9b679191a3fb610fed33dfe525e1",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Internal": false,
"Containers": {
"c5bdfc331017107be4ae1bdfff12e531b3eaa3424852c4404a301b1f1c28f31b": {
"Name": "container2",
"EndpointID": "04160448f248c68d37644da7dc4e4eff56e814a9efd9f4499095ece494cf6926",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"de95bdb8761f646a3f8423724f944f420e332fa3070bae1ff3fec127411e015e": {
"Name": "container1",
"EndpointID": "610a49518b5a15c28e3931fc20107c9e380c5c7b267feebd101a59e099977e43",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/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": "1500"
},
"Labels": {}
}
]
可以看到,增加的两个容器运行在了bridge网络,并且被分配了172.17.0.0/16子网下的IP地址:172.17.0.3/16和172.17.0.2/16.容器使用这个IP地址可以相互通信。
使用docker attach命令连上一个容器container1,并查看容器的ifconfig信息:
$ docker attach container1
/ # 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:1500 Metric:1
RX packets:66 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:9990 (9.7 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:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Docker引擎为该容器分配了一个虚拟的网络设备eth0,并为其分配了IP 172.17.0.2/16。 继续留在容器会话,用ping命令来测试容器之间的连通性,并查看容器/etc/hosts文件的内容
/ # 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.147 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.088 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.088 ms
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.088/0.107/0.147 ms
/ # 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
<span style="color:#FF0000;">172.17.0.2 de95bdb8761f</span>
也可以用同样的方式连接上container2查看网络信息并测试连通性。
现在再来看看主机的网络信息ifconfig,会发现多了两个网络接口:
veth94fa486 Link encap:Ethernet HWaddr 46:d9:22:67:7e:bf
inet6 addr: fe80::44d9:22ff:fe67:7ebf/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:14 errors:0 dropped:0 overruns:0 frame:0
TX packets:61 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1124 (1.1 KB) TX bytes:8778 (8.7 KB)
veth9dc4552 Link encap:Ethernet HWaddr 1a:8d:37:3e:a9:f1
inet6 addr: fe80::188d:37ff:fe3e:a9f1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:32 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:5084 (5.0 KB)
这两个名为vethXXXX的网络接口,正和container1和container2的eth0对应。他们与主机的docker0接口形成了网络管道,能让容器和主机互联——我们即可以在主机上ping通容器,也可以在容器里ping通主机:
$ ping -w3 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.040 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.051 ms
--- 172.17.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 0.040/0.055/0.079/0.016 ms
$ docker attach container1
/ # ping -w3 10.12.129.131
PING 10.12.129.131 (10.12.129.131): 56 data bytes
64 bytes from 10.12.129.131: seq=0 ttl=64 time=0.116 ms
64 bytes from 10.12.129.131: seq=1 ttl=64 time=0.092 ms
64 bytes from 10.12.129.131: seq=2 ttl=64 time=0.062 ms
--- 10.12.129.131 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.062/0.090/0.116 ms
运行在bridge网络的容器,可以通过发布端口的方法获得与主机所在的外界网络的通信。如在docker run命令中使用-P就能将容器所有的端口暴露出来,绑定到主机的某随机端口上
$ docker run -dP --name=nginxcontainer nginx
f7ada9face148d5123cfd89f70ba223f2f5090c50ee2081f742377e75d2abb79
$ docker port nginxcontainer
443/tcp -> 0.0.0.0:32770
80/tcp -> 0.0.0.0:32771
nginxcontainer容器创建在了bridge网络上,其443端口和80端口分别绑定到了主机的32770端口和32771上。使用curl命令能访问。
$ curl http://127.0.0.1:32771
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
下图很形象地展示了Docker bridge网络里运行的容器及端口暴露。
1.2 Docker的none网络
使用docker network inspect命令查看none的详细信息:
$ docker network inspect none
[
{
"Name": "none",
"Id": "0aba874b71562e7ec802a25ea8c6609ad295ff6ea6f3ea42633c9d7cf8b4133e",
"Scope": "local",
"Driver": "null",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": []
},
"Internal": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
目前该网络内还没有容器在运行。现在使用docker run命令增加容器
$ docker run --net=none -itd --name=container3 busybox
1996e52719ff3852efeabfe9f6accc504aa0d140f1be024c8fa9fb73e0dac704
再次用docker network inspect命令查看none网络的详细信息:
$ docker network inspect none
[
{
"Name": "none",
"Id": "0aba874b71562e7ec802a25ea8c6609ad295ff6ea6f3ea42633c9d7cf8b4133e",
"Scope": "local",
"Driver": "null",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": []
},
"Internal": false,
"Containers": {
"1996e52719ff3852efeabfe9f6accc504aa0d140f1be024c8fa9fb73e0dac704": {
"Name": "container3",
"EndpointID": "0745453691f3f8efaf47d8180f9b04f72c64bbcf4bc313ea9ba3ccb65bac6e4d",
"MacAddress": "",
"IPv4Address": "",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
可以看到,增加的容器运行在none网络,没有MAC地址,没有IP地址。使用docker attach命令连上该容器查看其网络配置:
$ docker attach container3
/ # 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:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # 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
<span style="color:#FF0000;">1996e52719ff</span>
/ #
Docker引擎没有为该容器分配虚拟的网络设备和IP地址。
1.3 Docker的host网络
使用docker network inspect命令查看host网络的详细信息:
$ docker network inspect host
[
{
"Name": "host",
"Id": "14984b1fcc40a9ea7a655048bbcda98c8142f24d68a072a21199266a218da511",
"Scope": "local",
"Driver": "host",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": []
},
"Internal": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
目前该网络内还没有容器在运行。现在使用docker run命令增加容器
$ docker run --net=host -itd --name=container4 busybox
c532064f4a98940a34f7185b9347025f0bb9bebf73474d1f8368bb50048a4f22
再次用docker network inspect命令查看host网络的详细信息:
$ docker network inspect host
[
{
"Name": "host",
"Id": "14984b1fcc40a9ea7a655048bbcda98c8142f24d68a072a21199266a218da511",
"Scope": "local",
"Driver": "host",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": []
},
"Internal": false,
"Containers": {
"c532064f4a98940a34f7185b9347025f0bb9bebf73474d1f8368bb50048a4f22": {
"Name": "container4",
"EndpointID": "e5100943faea59d3fe9ef247745528a1bf434ec6bd6702d102c56893d32a8696",
"MacAddress": "",
"IPv4Address": "",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
可以看到,增加的容器运行在host网络,同样没有MAC地址,没有IP地址。使用docker attach命令连上该容器查看其网络配置:
$ docker attach container4
/ # ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:BF:C2:8C:9A
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:bfff:fec2:8c9a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:37 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1100 (1.0 KiB) TX bytes:6055 (5.9 KiB)
enp4s0 Link encap:Ethernet HWaddr A4:1F:72:6B:4E:D9
inet addr:10.12.165.28 Bcast:10.12.165.255 Mask:255.255.255.0
inet6 addr: fe80::de02:484e:467d:7e83/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:51485 errors:0 dropped:0 overruns:0 frame:0
TX packets:32784 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:25389130 (24.2 MiB) TX bytes:6960263 (6.6 MiB)
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:5088 errors:0 dropped:0 overruns:0 frame:0
TX packets:5088 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:467265 (456.3 KiB) TX bytes:467265 (456.3 KiB)
veth435e89d Link encap:Ethernet HWaddr 4A:64:11:22:A9:B1
inet6 addr: fe80::4864:11ff:fe22:a9b1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:13 errors:0 dropped:0 overruns:0 frame:0
TX packets:46 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1026 (1.0 KiB) TX bytes:7094 (6.9 KiB)
veth9250953 Link encap:Ethernet HWaddr 0E:BA:74:68:E4:08
inet6 addr: fe80::cba:74ff:fe68:e408/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:13 errors:0 dropped:0 overruns:0 frame:0
TX packets:78 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1026 (1.0 KiB) TX bytes:11673 (11.3 KiB)
wlp3s0 Link encap:Ethernet HWaddr 1C:3E:84:98:71:A2
inet addr:10.12.137.123 Bcast:10.12.139.255 Mask:255.255.252.0
inet6 addr: fe80::c40f:83fe:c57:7f0a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:42260 errors:0 dropped:0 overruns:0 frame:0
TX packets:511 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:3733911 (3.5 MiB) TX bytes:92175 (90.0 KiB)
/ # cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 jiayuan-Vostro-270
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
容器的网络配置信息与所在的主机完全相同。这就意味着该主机能访问的网络,该容器也能访问。用ping命令来测试:
/ # ping -w3 jd.com
PING jd.com (111.206.227.118): 56 data bytes
64 bytes from 111.206.227.118: seq=0 ttl=53 time=1.886 ms
64 bytes from 111.206.227.118: seq=1 ttl=53 time=1.716 ms
64 bytes from 111.206.227.118: seq=2 ttl=53 time=1.564 ms
--- jd.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.564/1.722/1.886 ms
说明容器能访问jd.com
1.3 Docker的"container"网络
Docker还可以将容器运行在另一个容器的网络上,例如,上面的容器container1运行在bridge网络,现在再创建一个容器container7,用--net=container:container1来指定容器container7与container1共享一个网卡eth0
$ docker run --net=container:container1 -itd --name=container7 busybox
479a3b2e17bb634098a7b89cb088f813ab7bbe8d54988121ff06046eed479034
如果用docker network inspect bridge查看bridge网络,不会看到容器container7运行在该网络。但是container7也能和container1一样监听来自eth0的请求。用docker inspect container7命令查看容器的详细信息里NetworkMode为container:container1.
连上container7看看网络信息,发现container7和container1的网络接口信息完全相同,说明两个容器共享一个网卡eth0:
$ docker attach container7
/ # 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:1500 Metric:1
RX packets:28 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:4476 (4.3 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:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # 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
172.17.0.2 de95bdb8761f
Docker的这种网络模式,被Kubernetes用来创建Pod内部的网络环境。关于这个,我会在Kubernetes网络模型一文中介绍。:
2. 用户自定义网络
除了Docker自动创建的三个网络,用户可以为Docker创建新的网络。为Docker增加新的网络的方式有两种——使用Docker自带的bridge和overlay两种网络驱动,或提供新的网络插件。
用户可以创建多个网络,并且将容器运行在多个网络上。容器之间的通信只能在同一个网络里进行,容器之间不能跨网络通信。
2.1 使用bridge驱动创建网络
使用docker network create命令创建一个新的bridge网络
$ docker network create --driver bridge my_network
5d0513f620613f8e14d13ab44034be57ee40dada3a8a63159d8cad8c5b840ad9
使用ifconfig命令,可以看到,除了docker0,又多出一个br-5d0513f62061:
$ ifconfig
<span style="color:#FF0000;">br-5d0513f62061</span> Link encap:Ethernet HWaddr 02:42:eb:66:d2:0e
inet addr:172.18.0.1 Bcast:0.0.0.0 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)
docker0 Link encap:Ethernet HWaddr 02:42:bf:c2:8c:9a
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:bfff:fec2:8c9a/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:39 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1100 (1.1 KB) TX bytes:6418 (6.4 KB)
此时,使用docker network list命令可以看到多出了一个叫my_network的网络:
$ docker network ls
NETWORK ID NAME DRIVER
507d17743c82 bridge bridge
14984b1fcc40 host host
<span style="color:#FF0000;">5d0513f62061 my_network bridge </span>
0aba874b7156 none null
my_network网络的使用方式和1.1 Docker的bridge网络里介绍的bridge网络的使用方式完全相同,如下。
$ docker run --net=my_network -itd --name=container5 busybox
d54c5dd948a66b0835fca0e5a2ade03cf912bad832a3032967a9079292cd5836
$ docker network inspect my_network
[
{
"Name": "my_network",
"Id": "5d0513f620613f8e14d13ab44034be57ee40dada3a8a63159d8cad8c5b840ad9",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1/16"
}
]
},
"Internal": false,
"Containers": {
"d54c5dd948a66b0835fca0e5a2ade03cf912bad832a3032967a9079292cd5836": {
"Name": "container5",
"EndpointID": "0cf4df182681761b0fe2a07bbb71ae3fc87ebea7b8ed55831ef5c951c3bef9b9",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
$ docker attach container5
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:00:02
inet addr:172.18.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe12:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:54 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:8530 (8.3 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:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # 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
172.18.0.2 d54c5dd948a6
/ # ping -w3 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
可以看到容器container5运行在了my_network网络,并且被分配了172.18.0.0/16子网下的IP地址:172.18.0.2/16. 上面的操作还显示了运行在my_network网络里的容器container5无法和运行在bridge网络里的容器container2(IP地址为172.17.0.3)通信。
使用docker network connect命令可以将已经运行容器加入到另一个网络,如将container2加入到my_network网络:
$ docker network connect my_network container2
$ docker network inspect my_network
[
{
"Name": "my_network",
"Id": "5d0513f620613f8e14d13ab44034be57ee40dada3a8a63159d8cad8c5b840ad9",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1/16"
}
]
},
"Internal": false,
"Containers": {
"c5bdfc331017107be4ae1bdfff12e531b3eaa3424852c4404a301b1f1c28f31b": {
"Name": "container2",
"EndpointID": "ea05ecf305b8e71daf608cde09a41eb2c1efe322a9c07c0c38fa0df3bd26b47c",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"d54c5dd948a66b0835fca0e5a2ade03cf912bad832a3032967a9079292cd5836": {
"Name": "container5",
"EndpointID": "0cf4df182681761b0fe2a07bbb71ae3fc87ebea7b8ed55831ef5c951c3bef9b9",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
$ 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:1500 Metric:1
RX packets:50 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:7747 (7.5 KiB) TX bytes:1026 (1.0 KiB)
eth1 Link encap:Ethernet HWaddr 02:42:AC:12:00:03
inet addr:172.18.0.3 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe12:3/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:23 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:3577 (3.4 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:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # 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
<span style="color:#FF0000;">172.17.0.3 c5bdfc331017
172.18.0.3 c5bdfc331017</span>
/ # ping -w3 172.18.0.2
PING 172.18.0.2 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.126 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.096 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.096 ms
--- 172.18.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.096/0.106/0.126 ms
可以看到容器container2运行在了my_network网络,Docker引擎为该容器分配了一个新虚拟的网络设备eth1并分配了172.18.0.0/16子网下的IP地址:172.18.0.3/16. 现在container2和container5在my_network网络里可以互相通信,container2和container1在bridge网络里可以互相通信,而container1和container5由于不在同一个网络里,不能互相通信。
bridge模式下的网络适用于在单台主机上运行几个较小的相互隔离的网络。如果要创建跨主机的网络,可以使用overlay模式。
2.2 Docker overlay网络模式
本文只对Docker的overlay网络模式作简要介绍,其详细说明创建方法可参考Getting started for overlay.
Docker内置overlay网路模式驱动libnetwork,可以用于创建跨多个主机的网络。在同一个overlay网络里的容器,无论运行在哪个主机上,都能相互通信。
要创建overlay网络,首先要有一个提供key-value存储服务的服务器,当前Docker支持的key-value存储服务器有Consul, Etcd和ZooKeeper. 组成overlay网络的Docker的主机之间、Docker主机和key-value存储服务器之间都要能互通互联。在Docker主机上还要开放如下两个端口:
udp端口:4789,用于传输VXLAN网络数据的端口
tcp/udp端口:7946,用于控制平面的端口
对要加入overlay网络里里的每台Docker主机,都要完成如下配置:/span>
--cluster-store=PROVIDER://URL/span> 配置key-value存储服务器的地址
--cluster-advertise=HOST_IP|HOST_IFACE:PORT Docker所在的当前主机的地址和端口
--cluster-store-opt=KEY-VALUE OPTIONS 其他配置信息,如TLS证书等
然后用docker network create命令就能创建一个overlay网络,并能在该网络上创建容器。
$ docker network create --driver overlay my-multi-host-network
$ docker run -itd --net=my-multi-host-network busybox
作者猜想:Docker的overlay网络的原理应该是在key-value存储服务器上创建了ip地址表,当overlay网络里的容器相互通信时,通过查找key-value服务器上的ip地址标来找到目标容器所在的主机地址,经过地址转换(NAT)完成通信。待作者分析源码后看看是否猜想正确。
2.3 定制Docker网络插件
使用Docker的插件机制,用户也能通过开发网络插件来提供定制的Docker网络驱动。使用定制的网络插件来创建Docker网络的方法与上面所述的相同,一样是使用docker network create命令。例如,weave是用户提供的定制的网络驱动:
$ docker network create --driver weave mynet
$ docker run -itd --net=mynet busybox
上面的命令。创建了一个weave驱动的网络mynet,并在上面运行了一个容器。