一.docker网络类型(三种四种五种都行)

bridge

默认类型,docer启动后宿主机默认创建docker0,默认创建的容器的IP与docker0在一个网段

host

容器与宿主机共享网络,与宿主机一模一样,无独立的network namespace

none

容器没有可用IP,只有一个环回口网卡lo,无法与外界通信,network namespace是独立的

container

与指定的容器使用一模一样的network namespace,网卡配置相同

自定义

自定义network名字,实际是bridge类型,如--net lnmp,同一个lnmp同一个网段,从docker0里面重新划分一个子网

二.修改默认分配的容器IP网段与宿主机路由查看

docker启动默认有两个IP网段,可为容器分配IP,分配的IP默认是与docker0一个网段:

172.17.0.0/16 dev docker0

172.18.0.0/16 dev br-6d7ae1d4f0cb

#docker启动后未创建容器的情况下 宿主机上路由
[root@doker ~]# ip route  
default via 192.168.77.2 dev ens33 proto static metric 100  
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1  
172.18.0.0/16 dev br-6d7ae1d4f0cb proto kernel scope link src 172.18.0.1  
192.168.77.0/24 dev ens33 proto kernel scope link src 192.168.77.130 metric 100  
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

可以自定义容器的默认IP网段,/etc/docker/daemon.json,如定义容器的ip网段为10.10.0.0/16,注意daemon.json的每一类参数最后是逗号,分割的,上一类参数后面添加逗号后再添加内容

#/etc/docker/daemon.json增加以下的内容
 "default-address-pools": [
    {"base": "10.10.0.0/16", "size": 24}
 ]

修改后重启docker

systemctl restart docker

重启后172.17.0.0/16 dev docker0变为10.10.0.0/24 dev docker0

#docker启动后未创建容器的情况下 宿主机上路由,修改后
[root@doker ~]# ip route
default via 192.168.77.2 dev ens33 proto static metric 100 
10.10.0.0/24 dev docker0 proto kernel scope link src 10.10.0.1 
172.18.0.0/16 dev br-6d7ae1d4f0cb proto kernel scope link src 172.18.0.1 
192.168.77.0/24 dev ens33 proto kernel scope link src 192.168.77.130 metric 100 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

三.五种网络类型图解

bridge:默认类型,docer启动后宿主机默认创建docker0,默认创建的容器的IP与docker0在一个网段

docker网络类型与IP路由冲突排错_docker

#创建容器,默认网络类型bridge
docker run -itd --name bs1 busybox
#进入容器后查看IP
docker exec -it bs1 sh
#容器eth0的IP与docker0一个网段,还有一个环回口lo
ifconfig
#路由追踪,容器eth0的IP---docker0网关---宿主机eth0网关
traceroute 223.5.5.5

host:容器与宿主机共享网络,与宿主机一模一样,无独立的network namespace

docker网络类型与IP路由冲突排错_网络类型_02

#创建容器,指定网络类型host --net host
docker run -itd --name bs2 --net host busybox
#进入容器后查看IP
docker exec -it bs2 sh
#容器网卡与宿主机网卡一模一样
ifconfig
#路由追踪,直接到宿主机eth0网关
traceroute 223.5.5.5

none:容器没有可用IP,只有一个环回口网卡lo,无法与外界通信,network namespace是独立的

docker网络类型与IP路由冲突排错_IP_03

#创建容器,指定网络类型none --net none
docker run -itd --name bs3 --net none busybox
#进入容器后查看IP
docker exec -it bs3 sh
#只有一个环回口lo 127.0.0.1
ifconfig
#路由追踪,无法与外界通信
traceroute 223.5.5.5

container:与指定的容器使用一模一样的network namespace,网卡配置相同

docker网络类型与IP路由冲突排错_docker_04

#创建容器,指定容器名字 --net container:被指定的容器name
docker run -itd --name bs4 --net container:bs1 busybox
docker run -itd --name bs5 --net container:bs2 busybox
docker run -itd --name bs6 --net container:bs3 busybox
#进入容器后查看IP
docker exec -it bs4 sh
docker exec -it bs5 sh
docker exec -it bs6 sh
#与被指定的容器一模一样的网卡
ifconfig

自定义:如--net lnmp,实际还是bridge类型,从docker0大的网段中重新划分一个子网lnmp

docker网络类型与IP路由冲突排错_docker_05

#查看路由,多出一个属于lnmp的子网10.10.1.0/24 dev br-1d9e08dac25e,从docker0分出去的
[root@doker ~]# ip route
default via 192.168.77.2 dev ens33 proto static metric 100  
10.10.0.0/24 dev docker0 proto kernel scope link src 10.10.0.1  
10.10.1.0/24 dev br-1d9e08dac25e proto kernel scope link src 10.10.1.1  
172.18.0.0/16 dev br-6d7ae1d4f0cb proto kernel scope link src 172.18.0.1  
192.168.77.0/24 dev ens33 proto kernel scope link src 192.168.77.130 metric 100  
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
#创建自定义网络类型
docker network create lnmp
#查看没看到lnmp类型其实是bridge
docker network ls
#创建容器,指定自定义网络类型lnmp --net lnmp
docker run -itd --name bs7 --net lnmp busybox
docker run -itd --name bs8 --net lnmp busybox
docker run -itd --name bs9 --net lnmp busybox
#进入容器后查看IP
docker exec -it bs7 sh
docker exec -it bs8 sh
docker exec -it bs9 sh
#容器IP从10.10.1.0/24子网分配的
ifconfig
#路由追踪,traceroute:容器eth0的IP---新网桥br-xxx网关---宿主机eth0网关
traceroute 223.5.5.5

四.故障排查

问题现象:本地办公室电脑的客户端访问云上容器的web服务访问不到,容器web服务正常,云上安全组和本地防火墙都放行web服务的端口,排查宿主机的路由,发现了问题,云上容器返回本地电脑的路由匹配到了172.17.0.0/16走docker0了,没有走宿主机的eth0,出不去了。

这是为什么呢?因为默认路由查找的方式要遵循最长掩码匹配原则,试着分析一下

宿主机返回本地电脑172.17.16.229/24的路由,在宿主机路由表中匹配,没匹配到172.17.16.229/32主机路由......没匹配到172.17.16.0/24路由......匹配到了172.17.0.0/16,匹配到后,路由出口是容器的docker0,不是宿主机的eth0,这样就到不了本地电脑,导致本地电脑无法访问容器的web服务。

docker网络类型与IP路由冲突排错_IP_06

解决方式一:宿主机添加路由

#临时添加
route add -net 172.17.16.0 netmask 255.255.255.0 dev eth0
#永久添加
echo "route add -net 172.17.16.0 netmask 255.255.255.0 dev eth0" >>/etc/rc.local

docker网络类型与IP路由冲突排错_IP_07

解决方式二:更改容器IP,需要重启docker

/etc/docker/daemon.json增加分配给容器IP的网段,默认是172.17.0.0/16 如改为172.19.0.0/16,更改后,原来使用172.17.0.0/16网段的容器,IP也会也会随着更改,因为容器的服务端口是端口映射的,所以的服务没影响。

#/etc/docker/daemon.json增加以下的内容
 "default-address-pools": [
    {"base": "172.19.0.0/16", "size": 24}
 ]
 #重启docerk
 systemctl restart docker