docker网络通信
docker网络模型
docker默认采用docker0网桥实现容器之间及容器和宿主机之间的通信,模型如下:
每启动一个容器,会创建一对veth(linux bridge veth pair技术),一个置于容器中名为eth0,一个在宿主机上,并且绑定到docker0网桥上,可以通过brctl工具查看网桥信息。
这一对虚拟网卡设备,可以理解为有一根无形的网线连接着的,一端发数据一端即可收到。
一般docker0构建了一个子网,如172.17.0.1/24,容器ip都是该子网的ip如:172.17.0.2,172.17.0.6
而宿主机的ip则一般为192.168.16.111/24这种,明显两者不在统一网段,根据tcp/ip协议的规范,不同网段不能直接通信,那么docker是怎么处理的呢?
容器间访问
容器间通信实际上比较简单,容器之间互相通过arp协议互相知道对方mac地址,封装数据包时mac地址直接是对方mac,docker0充当二层交换机的角色,直接通过目标机mac地址找到网络接口,
如docker网络模型图,容器1需要和容器2通信,容器1通过arp协议知道了容器2的veth5c71391网卡mac地址02:42:8e:64:c4:4f,在封装数据包的时候直接将目标机mac填为02:42:8e:64:c4:4f。
当数据发送至docker0时,docker0查看mac和端口映射表(CAM表),发现02:42:8e:64:c4:4f对应的是veth5c71391接口,则直接将数据转发至veth5c71391网卡,进而到达容器2的eth0网卡。
容器访问外网
首先容器还是通过自己的eth0网卡发出数据,发现目标机ip不是本网段的,则发送至docker0,即到达了宿主机。
此时docker0也发现不是目标机ip不是本网段的,需要转发给其他网段处理,则查询主机路由表,发现目标地址命中了default规则,继而将数据转发至宿主机eth0接口,通过宿主机eth0网卡发往宿主机对应的网关,网关再进行路由发往外网。
主机路由表可通过route命令或者ip route查看
由结果看出,发往外网的都需要经过eth0网卡发往网关,发往容器的都需要由docker0网卡处理
外网访问容器
外网访问容器,一般是通过iptables DNAT功能来实现的。容器绑定宿主机端口的时候,docker默认写了一条防火墙规则,通过iptables -t nat -vnL PREROUTING命令查看,
意为:非docker0网卡进来的目标端口为6379的数据,将目的地替换为172.17.0.2:6379.
当数据从网卡进入网络协议栈之后,大致过程如下
以上均为个人理解,如有错误,还望指正,共同进步!