理解Docker0
首先我们来看一下宿主机的网卡配置ifconfig
,可以看到一张叫做docker0
的网卡
root@ubuntu:/home/xiaoh# ifconfig
#docker0网卡信息
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:9a:8c:3a:75 txqueuelen 0 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#内网网卡信息
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.43.103 netmask 255.255.255.0 broadcast 192.168.43.255
inet6 240e:43d:8908:779:fc07:3c2e:e836:a4e1 prefixlen 64 scopeid 0x0<global>
inet6 fe80::a7e0:f8c:8e15:2b51 prefixlen 64 scopeid 0x20<link>
inet6 240e:43d:8908:779:2fe9:ecc9:cf0e:ac0e prefixlen 64 scopeid 0x0<global>
ether 00:0c:29:28:0f:24 txqueuelen 1000 (以太网)
RX packets 133 bytes 48755 (48.7 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 229 bytes 31723 (31.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#本地环回信息
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (本地环回)
RX packets 185 bytes 15677 (15.6 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 185 bytes 15677 (15.6 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
那 么Docker是如何处理网络配置的?我们来测试一下
#启动容器
docker run -d -P --name tomcat01 tomcat
#进入容器并下载网络命令
docker exec -it tomcat01 /bin/bash
apt update && apt install -y iproute2
#查看网络
ip addr
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
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#ping容器
ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 比特,来自 172.17.0.2: icmp_seq=1 ttl=64 时间=0.279 毫秒
64 比特,来自 172.17.0.2: icmp_seq=2 ttl=64 时间=0.051 毫秒
...
我们每启动一个docker容器,docker就会给容器分配一个ip,我们只要安装了docker,宿主机上就会有一张docker0
网卡。并且使用桥接模式,使用的技术是evth-pair
技术!
查看主机和容器网卡
#容器内网卡
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#主机网卡
#发现多了一张网卡,这就是与容器配对的网卡
7: vethbb2bae3@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether a2:6d:e1:7e:b7:fb brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::a06d:e1ff:fe7e:b7fb/64 scope link
valid_lft forever preferred_lft forever
evth-pair技术
我们发现容器带来的网卡都是成对的。容器内有一张网卡,主机也会增加一张网卡。
evth-pair技术就是一对虚拟的设备接口,它们都是成对出现的,一端连着协议,一端彼此相连。正是因为这个特性,evth-pair技术就像一个桥梁,能够连接各种虚拟网络设备。Openstac、Docker容器之间的连接、OVS的连接都是使用的evth-pair技术。
tomcat01和tomcat02相当于共用一个路由器docker0。当容器不指定网络的情况下,都是docker0路由,docker会给容器分配一个默认可用的ip。Docker所有的网络接口都是虚拟的,转发效率高。
宿主机中使用的网卡是Docker容器的网桥——docker0。
容器互联
首先测试容器之间是否能通过容器名ping通
#容器内安装ping命令
apt-get install inetutils-ping
#测试,无法ping通
docker exec -it tomcat02 ping tomcat01
ping: unknown host
可以使用--link
选项来连通两个容器
#连通启动
docker run -d -P --name tomcat03 --link tomcat02 tomcat
#测试ping
docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.088 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.075 ms
--- tomcat02 ping statistics ---
#问题是只能tomcat01ping通tomcat02,而无法反过来。
我们可以使用docker network
来查看容器网络配置
#列出网络
dockers network ls
NETWORK ID NAME DRIVER SCOPE
443a88c2886f bridge bridge local
d7d5810dcb43 host host local
53fb3ec12878 none null local
#查看某一容器网络详细信息
docker network inspect netid
实际上,--link
选项就是为容器配置绑定了一个映射,我们来看一下tomcat03
的网络配置信息
root@ubuntu:/home/xiaoh# docker exec -it tomcat03 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
#这里将容器名tomcat02和ip地址绑定了起来
172.17.0.3 tomcat02 77d2321a028f
172.17.0.4 7f2541ad86e5
自定义网络
使用docker network
命令
网络模式
网络模式 | 解释 |
bridge | 桥接模式(docker默认,自己创建网络也常使用该模式) |
none | 不配置网络 |
host | 与宿主机共享网络 |
container | 容器网络连通(局限较大) |
测试自定义网络
#我们直接启动的命令默认是使用 --net bridge ,这张网卡就是docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
#docker0特点:默认,无法访问域名,需要使用--link来手动连接容器
创建自定义网络
#--driver 网络模式,默认为bridge
#--subnet 子网地址
#--gateway 网关地址
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
#查看网络
root@ubuntu:/home/xiaoh# docker network ls
NETWORK ID NAME DRIVER SCOPE
443a88c2886f bridge bridge local
d7d5810dcb43 host host local
31d5effd27a3 mynet bridge local
53fb3ec12878 none null local
#查看网络详细信息
root@ubuntu:/home/xiaoh# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "31d5effd27a316bb5e921c5a37c1d2a4c5f2d9462ce2524371189984313a5fb4",
"Created": "2022-01-17T22:44:18.531124517-08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
使用自定义网络
root@ubuntu:/home/xiaoh# docker run -d -P --name tomcat-net-01 --net mynet tomcat
07c4b65fc1081ebb89a3fe494f7e5763882284c5b7797626884e7a028f4be74c
root@ubuntu:/home/xiaoh# docker run -d -P --name tomcat-net-02 --net mynet tomcat
99435bf3b387e20a9892cb9ddbe1e185624b704d3650f2ea07b172a4f4eeaaaf
#查看自定义网络
#可以看到有两个容器使用我们的自定义网络
...
"Containers": {
"07c4b65fc1081ebb89a3fe494f7e5763882284c5b7797626884e7a028f4be74c": {
"Name": "tomcat-net-01",
"EndpointID": "17b8689e18b11494ee72935ba3354fcc8722a8c85716c0866d3fecb5e55fb1c3",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"99435bf3b387e20a9892cb9ddbe1e185624b704d3650f2ea07b172a4f4eeaaaf": {
"Name": "tomcat-net-02",
"EndpointID": "53183d1e5621fd077c806cf892d833911efb7f542c40d9af9dbd30eeed0df9d2",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
...
#并且容器之间是可以通过容器名ping通的
root@ubuntu:/home/xiaoh# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3): 56 data bytes
64 bytes from 192.168.0.3: icmp_seq=0 ttl=64 time=0.077 ms
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.083 ms
--- tomcat-net-02 ping statistics ---
自定义的docker网络已经帮我们维护好了对应的网络关系!
网络连通
假如碰到了下图中的情况,位于172网段的容器,需要连接位于192网段的容器,那么我们该怎么实现呢?
测试连通不同网段容器
可以使用docker network connect
命令
#将tomcat01容器和mynet网络连接
docker network connect mynet tomcat01
#查看mynet网络信息
docker network inspect mynet
"Containers": {
"07c4b65fc1081ebb89a3fe494f7e5763882284c5b7797626884e7a028f4be74c": {
"Name": "tomcat-net-01",
"EndpointID": "17b8689e18b11494ee72935ba3354fcc8722a8c85716c0866d3fecb5e55fb1c3",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"99435bf3b387e20a9892cb9ddbe1e185624b704d3650f2ea07b172a4f4eeaaaf": {
"Name": "tomcat-net-02",
"EndpointID": "53183d1e5621fd077c806cf892d833911efb7f542c40d9af9dbd30eeed0df9d2",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
#直接将tomcat01加到了mynet网络内,实现了一个容器两个地址 "f083d51615c27c1ac09bae53c8ab0f0e80ebb75d28ec2437c2491db75b1ef906": {
"Name": "tomcat01",
"EndpointID": "5d77efb5d9bf7879513ffcfc03606e851d35fc5b5fc78151c452b73d95ac1951",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
}
}
#测试成功ping通
root@ubuntu:/home/xiaoh# docker exec -it tomcat-net-01 ping tomcat01
PING tomcat01 (192.168.0.4): 56 data bytes
64 bytes from 192.168.0.4: icmp_seq=0 ttl=64 time=0.114 ms
64 bytes from 192.168.0.4: icmp_seq=1 ttl=64 time=0.216 ms
64 bytes from 192.168.0.4: icmp_seq=2 ttl=64 time=0.075 ms
--- tomcat01 ping statistics ---
参考文章