一、Docker网络bridge模型

bridge网络模型:创建容器时会自动创建一对veth,一端在docker0桥上,一端在容器名称空间中,容器借助NAT规则来实现暴露容器服务或者容器访问外网;
host网络模型:容器与host共用网络名称空间,要求容器的IP地址与容器服务的端口号与host不能冲突。
1.1 bridge桥
bridge name bridge id STP enabled interfacesdocker0 8000.02423ff697d4 no veth72f924eveth899f774
~]$ docker network lsNETWORK ID NAME DRIVER SCOPEbf78f07fecab bridge bridge local208d9a020e57 host host local9cd732fd1232 none null local
~]$ docker network inspect bf78f07fecab[{"Name": "bridge","Id": "bf78f07fecab039033608265bed6e1d53a10e037bb996c58d28d86f491bf5cc2","Created": "2021-04-19T12:40:01.789430412+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.18.0.0/16","Gateway": "172.18.0.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {"55e747767bf618a458533e601ebe11308a1ab2e86ec3450bc880ff671c751d6e": {"Name": "repository","EndpointID": "44c5ede5faf9a9eaefb49d3a93eb855f82a8cfc1ebda93dd475612039e430081","MacAddress": "02:42:ac:12:00:02","IPv4Address": "172.18.0.2/16","IPv6Address": ""},"ff858669f2ae3770ad10c2321da58116418a336ba49656a9a8b04fb3148b0999": {"Name": "nigelpoulton","EndpointID": "e5efe22b548acf81c457dadc3754fde4737d64f2495e0c3fab02d4dbd62df33e","MacAddress": "02:42:ac:12:00:03","IPv4Address": "172.18.0.3/16","IPv6Address": ""}},"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": {}}]
1.2 container veth
~]$ ip link show | grep veth30: veth72f924e@if29: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default42: veth899f774@if41: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
[root@file_repository-172.17.61.200 ~]$ docker container exec 2a00f5084711 ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever41: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UPlink/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ffinet 172.18.0.4/16 brd 172.18.255.255 scope global eth0valid_lft forever preferred_lft forever[root@file_repository-172.17.61.200 ~]$ docker container exec 55e747767bf6 ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever29: eth0@if30: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0valid_lft forever preferred_lft forever
[root@file_repository-172.17.61.200 ~]$ docker container exec 55e747767bf6 route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 172.18.0.1 0.0.0.0 UG 0 0 0 eth0172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0[root@file_repository-172.17.61.200 ~]$ docker container exec 2a00f5084711 route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 172.18.0.1 0.0.0.0 UG 0 0 0 eth0172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
可以看出容器的gateway均指向docker0桥。
二、同Host中Docker Container之间通信
~]$ docker container exec 2a00f5084711 ping 172.18.0.2
~]$ tcpdump -i docker0 -nntcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes20:02:37.829256 IP 172.18.0.4 > 172.18.0.2: ICMP echo request, id 26880, seq 16, length 6420:02:37.829358 IP 172.18.0.2 > 172.18.0.4: ICMP echo reply, id 26880, seq 16, length 6420:02:38.829514 IP 172.18.0.4 > 172.18.0.2: ICMP echo request, id 26880, seq 17, length 6420:02:38.829586 IP 172.18.0.2 > 172.18.0.4: ICMP echo reply, id 26880, seq 17, length 64
通过抓包分析同Host中的不通container通信通过二层的docker0即可实现,且是二层互通。
docker container exec 2a00f5084711 arp -a? (172.18.0.2) at 02:42:ac:12:00:02 [ether] on eth0? (172.18.0.1) at 02:42:3f:f6:97:d4 [ether] on eth0
三、外网与Docker Container之间通信
3.1 Docker Container访问外网
~]$ docker container exec 2a00f5084711 ping 114.114.114.114
[root@file_repository-172.17.61.200 ~]$ tcpdump -i eth0 -nn -p icmptcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes20:06:13.851823 IP 10.1.120.200 > 114.114.114.114: ICMP echo request, id 29696, seq 44, length 6420:06:13.879199 IP 114.114.114.114 > 10.1.120.200: ICMP echo reply, id 29696, seq 44, length 6420:06:14.249643 IP 10.1.120.200 > 114.114.114.114: ICMP echo request, id 30976, seq 38, length 6420:06:14.276981 IP 114.114.114.114 > 10.1.120.200: ICMP echo reply, id 30976, seq 38, length 6420:06:14.852054 IP 10.1.120.200 > 114.114.114.114: ICMP echo request, id 29696, seq 45, length 6420:06:14.879186 IP 114.114.114.114 > 10.1.120.200: ICMP echo reply, id 29696, seq 45, length 6420:06:15.249888 IP 10.1.120.200 > 114.114.114.114: ICMP echo request, id 30976, seq 39, length 6420:06:15.277086 IP 114.114.114.114 > 10.1.120.200: ICMP echo reply, id 30976, seq 39, length 64[root@file_repository-172.17.61.200 ~]$ tcpdump -i docker0 -nntcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on docker0, link-type EN10MB (Ethernet), capture size 262144 bytes20:06:45.858726 IP 172.18.0.4 > 114.114.114.114: ICMP echo request, id 29696, seq 76, length 6420:06:45.885721 IP 172.18.0.4 > 172.18.0.2: ICMP echo request, id 26880, seq 264, length 6420:06:45.885771 IP 172.18.0.2 > 172.18.0.4: ICMP echo reply, id 26880, seq 264, length 6420:06:45.885819 IP 114.114.114.114 > 172.18.0.4: ICMP echo reply, id 29696, seq 76, length 6420:06:46.256739 IP 172.18.0.4 > 114.114.114.114: ICMP echo request, id 30976, seq 70, length 6420:06:46.284265 IP 114.114.114.114 > 172.18.0.4: ICMP echo reply, id 30976, seq 70, length 6420:06:46.858940 IP 172.18.0.4 > 114.114.114.114: ICMP echo request, id 29696, seq 77, length 6420:06:46.885944 IP 172.18.0.4 > 172.18.0.2: ICMP echo request, id 26880, seq 265, length 64
通过抓包分析,在docker0抓包结果可看出源地址为172.18.0.4的容器地址,而在eth0的抓包结果看出源地址为eth0的地址,原因是container在访问外网时候进行SNAT。而SNAT中关键的一条规则如下,意思是来自任意网口且地址为172.18.0.0/16,流向非docker0的流量都转换为Host主机地址:
~]$ iptables -t nat -vnL POSTROUTINGChain POSTROUTING (policy ACCEPT 319K packets, 26M bytes)pkts bytes target prot opt in out source destination232 14427 MASQUERADE all -- * !docker0 172.18.0.0/16 0.0.0.0/0
3.2 外网访问Docker Container
containe的服务默认是不能被外网访问的,除非使用docker run -p暴露了端口,一旦将container端口暴露在Host上,外界流量就可经由DNAT规则到达container,而每一个暴露的端口在Host都有与之对应的docker-proxy进程。
~]$ iptables -t nat -vnL POSTROUTINGChain POSTROUTING (policy ACCEPT 319K packets, 26M bytes)pkts bytes target prot opt in out source destination0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:80600 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:1443
~]$ ps -ef | grep proxy | grep -v greproot 896 1683 0 Jul13 ? 00:00:09 usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.18.0.2 -container-port 8060root 910 1683 0 Jul13 ? 00:00:08 usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 443 -container-ip 172.18.0.2 -container-port 1443root 1322 1 0 Apr19 ? 00:00:00 usr/sbin/gssproxy -D
文章转载自运维扫盲人,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




