首先我们使用下面命令查看网络信息:
[vagrant@localhost ~]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
dce12ad15e67 bridge bridge local
be63d9693f78 host host local
d1c04eee03c8 none null local
今天要讨论的就是Linux的bridge网络。
之前我们使用ip a命令查看宿主机网络接口的时候,返回结果如下:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:5f:94:78 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic eth0
valid_lft 76814sec preferred_lft 76814sec
inet6 fe80::5054:ff:fe5f:9478/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:08:96:2b:f9 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:8ff:fe96:2bf9/64 scope link
valid_lft forever preferred_lft forever
59: vetha65affd@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 5a:31:ef:f0:fb:64 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::5831:efff:fef0:fb64/64 scope link
valid_lft forever preferred_lft forever
其中的veth开头的网络接口就是上一节介绍的veth-pair接口中的其中一个,而另外一个就是容器中的veth网络接口。如当前宿主机中已经启动的容器busybox1的网络接口信息如下:
[vagrant@localhost ~]$ sudo docker exec aec1c356e72c ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
58: eth0@if59: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
其中的eth0端口就是容器与宿主主机中的veth接口组成一对的网络接口,这也是容器可以连接上互联网的原因。而实际上容器也是通过这对veth接口最终连接上了宿主机的docker0端口,为了验证这句话,这里使用brctl工具,这个工具要先安装一下:
sudo yum install bridge-utils
安装以后,执行brctl show命令:
vagrant@localhost ~]$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024208962bf9 no vetha65affd
上面输出表明宿主机docker0接口和宿主机的vetha65affd接口的关系。
容器和互联网通信的网络如下:
由上图可知一个linux主机通过eth0接口连接互联网,容器显示连接到docker0,然后通过NAT(network address transtation,网络地址转换),最后通过eth0接口连接互联网。实际上两个容器通过veth-pair连接的过程中也是通过docker0关联的。
深入
之前我们执行sudo docker network ls来查看宿主机网络信息:
[vagrant@localhost ~]$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
dce12ad15e67 bridge bridge local
be63d9693f78 host host local
d1c04eee03c8 none null local
当我们创建一个容器后,容器就会自动连接到bridge网络上。此外,我们可以使用命令,让容器不连接到bridge网络上,而是连接到我们自己创建的网络上,请看下面:
- 首先创建一个名为my-bridge网络
sudo docker network create -d bridge my-bridge
结果如下:
[vagrant@localhost ~]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
dce12ad15e67 bridge bridge local
be63d9693f78 host host local
ec80468730b6 my-bridge bridge local
d1c04eee03c8 none null local
我们使用brctl show命令来查看bridge信息,除了docker0这个bridge信息外,还有一个我们新创建的bridge:my-bridge:
[vagrant@localhost ~]$ brctl show
bridge name bridge id STP enabled interfaces
br-ec80468730b6 8000.02420153f2be no
docker0 8000.024208962bf9 no vetha65affd
可以看出新创建的network此时还没有其他容器对其连接。
- 创建容器的时候连接到自己创建的bridge
现在我们新创建一个容器,并将这个容器连接到my-bridge上,而不是默认的docker0上:
docker run -d --name my-busybox --network my-bridge hub.c.163.com/library/busybox:latest /bin/sh -c "while true;do sleep 3600;done"
此时:
[vagrant@localhost ~]$ brctl show
bridge name bridge id STP enabled interfaces
br-ec80468730b6 8000.02420153f2be no veth2f2686c
docker0 8000.024208962bf9 no vetha65affd
可以看到此时我们新增的network已经有容器的veth网络端口连接上了。
我们也可以使用:
docker network inspect ec80468730b6
命令来查看具体的网络信息,最后一个参数为network id,在返回的json串中有一段:
"Containers": {
"9189e44ffc8026c63216343126e43dbfec455a212beff342df64c70242c98c9d": {
"Name": "my-busybox",
"EndpointID": "1254c2f18629884fdbdcfa2d0cc9f790c1d2de679e9b90417de7e4d4b18873e6",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
表示连接到这个network的容器信息,可以看到就是我们新创建的容器my-busybox。
3.修改已运行的容器连接到其他的bridge:
docker network connect my-bridge test1
上述命令将正在运行的test1容器网络端口连接到my-bridge。修改连接后,再次执行:
docker network inspect ec80468730b6
结果中Containers部分多了个test1容器的信息。另外,原来test1容器连接的docker0这个bridge网络interface信息中还是保留了连接,即一个容器可以连接到多个bridge上。
还需要注意的是当两个容器连接到了同一个bridge上,则两个容器之间就可以相互ping通。