bridge网络简介
bridge是docker默认使用的网络驱动。当启动容器时如果没有指定自定义的网络,那么容器会连接到默认的bridge网络上来进行容器间的通信。
bridge往往用在单机版的docker主机上,例如使用docker run命令运行的容器服务,或者使用Docker Compose做单机版的服务编排等。
接下来,来了解一下默认的bridge网络和自定义的bridge网络的异同。
默认的bridge网络
默认情况下,安装好docker后,会创建3个默认的网络,如下:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
8d87bbdc56e2 bridge bridge local
4aa478a3a4be host host local
28b0a9167669 none null local
查看bridge网络的详情
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "8d87bbdc56e21349811382d86a995c8a1b5831879f6984827d7abec0b424b589",
"Created": "2020-04-07T11:46:30.47790705+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"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": {}
}
]
可以看到bridge网络的网段为"Subnet": "172.17.0.0/16",此时"Containers": {},意味着目前还没有容器注册到这个网络上。
查看宿主机的网卡
$ ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:21:aa:7f:9c txqueuelen 0 (Ethernet)
RX packets 32 bytes 2280 (2.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27 bytes 3362 (3.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.255.0.154 netmask 255.255.255.0 broadcast 10.255.0.255
ether 00:50:56:d2:d7:a2 txqueuelen 1000 (Ethernet)
RX packets 21822647 bytes 3782719765 (3.5 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 25444957 bytes 9623684707 (8.9 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
可以看到除了eth0外,还有一个名为docker0的网卡,它的网段跟默认的bridge网络的网段是一致的。所以,对于启动的容器在没有指定自定义的网络的时候,会使用bridge网络通过docker0这个虚拟网卡跟宿主机的以太网接口进行网络通信。
使用默认的bridge网络验证容器间的通信
使用镜像alpine:3.10来启动两个容器观察网络连接和通信。
$ docker run --name alpine_1 -itd alpine:3.10
$ docker run --name alpine_2 -itd alpine:3.10
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
568162d425f6 alpine:3.10 "/bin/sh" 6 minutes ago Up 6 minutes alpine_2
ea10b7febc32 alpine:3.10 "/bin/sh" 6 minutes ago Up 6 minutes alpine_1
以上分别启动了两个以后台进程的方式运行的提供tty的名称为alpine1和alpine2的两个容器。再次查看bridge网络的详细信息。
$ docker network inspect bridge
[
{
...
"Containers": {
"568162d425f6b683fef1676dcac635b896035419a0733f5cc6375b7b4acf5033": {
"Name": "alpine_2",
"EndpointID": "5f9aca01e4e5d284ad9eebf1090d592768ce037a9b5f42ca9dd3c9eec5a74f9a",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"ea10b7febc326d558587b56aaeb2ce170f57e987db4013bc17e8e1de8357dbe8": {
"Name": "alpine_1",
"EndpointID": "e8de284514017c8cba7d203b8c8940594d1ddf53ba9ea7d1ca0fdc2da7215b82",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
...
}
]
可以看到当前启动的2个容器都已经连接到bridge网络,IP分别为172.17.0.2和172.17.0.3。
接下来再以容器方面来看一下网络连接。
进入容器alpine_1
$ docker exec -it alpine_1
查看alpine_1的ip
# 容器内
$ ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING 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)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
可以看到alpine_1的ip地址为172.17.0.2,跟bridge网络的详细信息中的网段是一致的。
容器网络通信
在alpine1的容器里ping一下alpine2的ip
$ ping -c 2 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.151 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.145 ms
--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.145/0.148/0.151 ms
两个容器使用ip是可以互通的,其中 -c 2意思是指发送两个数据包。
在alpine1的容器里ping一下alpine2的主机名
$ ping -c 2 alpine_2
ping: bad address 'alpine_2'
发现容器间使用主机名称不能解析到ip进而通信。
修改默认的bridge网络配置
想要修改默认的bridge网络的配置,需要修改/etc/docker/daemon.json配置文件,而后重启docker服务即可。
例如:
vi /etc/docker/daemon.json
{
"bip": "192.168.1.5/24",
"fixed-cidr": "192.168.1.5/25",
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "10.20.1.1",
"default-gateway-v6": "2001:db8:abcd::89",
"dns": ["10.20.1.2","10.20.1.3"]
}
其中的配置项参考链接:
https://docs.docker.com/engine/reference/commandline/dockerd/
注: 修改默认的bridge的网络配置,对所有未使用自定义网络的容器都生效。
自定义bridge网络
新建bridge网络
新建一个名称为alpine-net的bridge网络
$ docker network create --driver bridge alpine-net
--driver选项指定了网络的驱动类型为bridge,alpine-net是为定义的网络起的名称。
查看网络
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
8a7cd7747e5b alpine-net bridge local
8d87bbdc56e2 bridge bridge local
4aa478a3a4be host host local
28b0a9167669 none null local
查看alpine-net的详细信息
$ docker network inspect alpine-net
[
{
"Name": "alpine-net",
"Id": "8a7cd7747e5bf56f45b1c1d762f88dbbe63774eb5bec24bedbc9b4bba40f1f4d",
"Created": "2020-05-26T11:44:03.179651245+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
可以看到网段为:172.20.0.0/16,没有容器注册上来。
查看宿主机的网卡
$ ifconfig
...
br-8a7cd7747e5b: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.20.0.1 netmask 255.255.0.0 broadcast 172.20.255.255
ether 02:42:49:0d:11:3f txqueuelen 0 (Ethernet)
RX packets 32 bytes 2280 (2.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 27 bytes 3362 (3.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
...
可以看到多了一个虚拟网卡,其网关地址:172.20.0.1,跟新建的bridge网络在同一个网段。
使用镜像alpine:3.10再来启动另外的两个容器alpine3和alpine4,连接到自定义的网络alpine-net上。
$ docker run --name alpine_3 --network alpine-net -itd alpine:3.10
$ docker run --name alpine_4 --network alpine-net -itd alpine:3.10
容器网络通信
进入容器内部验证网络连接和容器间的通信。
$ docker exec -it alpine_3 sh
$ ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:14:00:02
inet addr:172.20.0.2 Bcast:172.20.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING 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)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
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:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
容器alpine_3的ip在172.20.0.0的网段上,说明确实连接的是alpine-net自定义的bridge网络。
在alpine3中分别ping一下alpine4的ip和主机名
$ ping -c 2 172.20.0.3
PING 172.20.0.3 (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.264 ms
64 bytes from 172.20.0.3: seq=1 ttl=64 time=0.182 ms
--- 172.20.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.182/0.223/0.264 ms
$ ping -c 2 alpine_4
PING alpine_4 (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.254 ms
64 bytes from 172.20.0.3: seq=1 ttl=64 time=0.163 ms
--- alpine_4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.163/0.208/0.254 ms
发现在自定义的bridge网络中容器间是可以使用主机名来进行网络通信的。
默认的bridge网络和自定义的bridge网络的区别
自定义的bridge网络可在容器之间提供DNS解析。
指的是容器间可以通过主机名称进行通信。
自定义的bridge网络可提供更好的网络隔离。
使用自定的bridge网络可以屏蔽其他无关的容器服务,使得只有连接在自定义的bridge网络上的容器间可以通信。
容器可以随时随地从自定义的网络连接和断开。
使用命令docker network connect/disconnect指令,可以方便的连接和断开自定义的网络。如果连接的是默认的bridge网络,需要先停止并删除容器,而后重新创建并连接到其他的网络上。
自定义的网络可以方便的自定义网络的配置。
使用默认的bridge网络,修改配置后,需要重启docker服务,而且是对连接在默认的bridge网络上的容器都生效。自定的bridge可以方便的配置,并只对部分容器生效。
默认的bridge网络可以共享环境变量。
自定义的网络是无法直接共享环境变量的,可以采用其他措施,比如共享容器卷的方式等。
好了,Docker的bridge网络的学习到此就结束了。如果有收获欢迎分享给你的朋友一起学习和讨论,也欢迎扫码关注公众号进击的极客。
相关链接:
Docker系列之网络篇
Docker系列之Docker的安装与配置