ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker 网络(二)Bridge 模式详解

Docker 网络(二)Bridge 模式详解 在 Bridge 模式下Docker 除了分配隔离的网络命名空间之外还会为所有的容器设置 IP 地址。当 Docker 服务器在主机上启动之后会创建新的虚拟网桥 docker0随后在该主机上启动的全部服务在默认情况下都会与该网桥相连。docker0 网桥使用 brctl show 命令可以查看到此时系统没有容器运行rootdocker-host:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES rootdocker-host:~# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242df573fac no rootdocker-host:~#现在运行三个容器分别是 nginxredismysqlrootdocker-host:~# docker run -d --name nginx -p 8080:80 nginx 56e6a37041cb7478b2f908fa7edb11bc972eee9dbaea475db4f4ec6783b1e43f rootdocker-host:~# docker run -d --name redis -p 6379:6379 redis cb57d69b1b9f5a489d32d53bcbae3ddca3823d50fbb4b3891ebbc4290285b468 rootdocker-host:~# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD123 -p 3306:3306 mysql 67549d3119b261d58783e6a45d074d7f2b89eb65fc930752d0cbe02707a132c4 rootdocker-host:~# rootdocker-host:~# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 56bd0d50081c mysql docker-entrypoint.s… 3 seconds ago Up 2 seconds 0.0.0.0:3306-3306/tcp, :::3306-3306/tcp, 33060/tcp mysql 9199dd045fd9 redis docker-entrypoint.s… 6 seconds ago Up 6 seconds 0.0.0.0:6379-6379/tcp, :::6379-6379/tcp redis af71f1490444 nginx /docker-entrypoint.… 9 seconds ago Up 9 seconds 0.0.0.0:8080-80/tcp, :::8080-80/tcp nginx rootdocker-host:~#现在检查网桥和 iptables注意标注的信息rootdocker-host:~# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242df573fac no vethf4a4032 vethf5e5a3c vethfab2a5a rootdocker-host:~# iptables -t nat -L Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere !localhost/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 anywhere MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:http MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:6379 MASQUERADE tcp -- 172.17.0.4 172.17.0.4 tcp dpt:mysql Chain DOCKER (2 references) target prot opt source destination RETURN all -- anywhere anywhere DNAT tcp -- anywhere anywhere tcp dpt:http-alt to:172.17.0.2:80 DNAT tcp -- anywhere anywhere tcp dpt:6379 to:172.17.0.3:6379 DNAT tcp -- anywhere anywhere tcp dpt:mysql to:172.17.0.4:3306 rootdocker-host:~#可以看出docker0 为每一个容器分配一个新的 IP 地址并将 docker0 的 IP 地址设置为默认的网关其拓扑关系如下比如mysql 容器的 ip 是 172.17.0.4Docker 网桥规则会将从任意源发送到当前机器 3306 端口的 TCP 包都转发到172.17.0.4:3306 所在的地址上如果在当前机器上直接 ping 这个 IP 地址就会发现它是可以访问到的rootdocker-host:~# ping 172.17.0.4 -c 3 PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data. 64 bytes from 172.17.0.4: icmp_seq1 ttl64 time0.086 ms 64 bytes from 172.17.0.4: icmp_seq2 ttl64 time0.056 ms 64 bytes from 172.17.0.4: icmp_seq3 ttl64 time0.064 ms --- 172.17.0.4 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2046ms rtt min/avg/max/mdev 0.056/0.068/0.086/0.012 ms rootdocker-host:~#从上述操作我们可以知道 Docker 是如何将容器的内部的端口暴露出来并对数据包进行转发的当有 Docker 容器需要将服务暴露给宿主机机器时docker0 就为容器分配一个 ip 地址同时向 iptables 追加一条新的转发规则。我们可以通过测试 mysql 服务器是否正常运行来理解上述 Docker 的网络转发过程rootdocker-host:~# mysqladmin -h 127.0.0.1 -P 3306 -u root -p ping Enter password: mysqld is alive rootdocker-host:~#使用 mysqladmin 客户机在宿主机的命令行中访问 127.0.0.1:3306 地址时会经过 iptables 的预路由NAT PREROUTING将该 ip 定向到了 mysql 容器的 ip 地址 172.17.0.4重定向过的数据包此时就可以通过 iptables 中的过滤转发FILTER FORWARD配置最终在后路由NAT POSTROUTING阶段将容器 ip 地址伪装成主机的 127.0.0.1此时虽然从外面看起来请求的是 127.0.0.1:3306但实际上请求的已经是 Docker 容器暴露出的端口了。在/sys/class/net目录可以查看到以上的所有网络设备rootdocker-host:~# ls -l /sys/class/net total 0 lrwxrwxrwx 1 root root 0 Jul 6 23:34 docker0 - ../../devices/virtual/net/docker0 lrwxrwxrwx 1 root root 0 Jul 6 23:34 ens33 - ../../devices/pci0000:00/0000:00:11.0/0000:02:01.0/net/ens33 lrwxrwxrwx 1 root root 0 Jul 6 23:33 lo - ../../devices/virtual/net/lo lrwxrwxrwx 1 root root 0 Jul 7 00:30 vethf4a4032 - ../../devices/virtual/net/vethf4a4032 lrwxrwxrwx 1 root root 0 Jul 7 00:30 vethf5e5a3c - ../../devices/virtual/net/vethf5e5a3c lrwxrwxrwx 1 root root 0 Jul 7 00:30 vethfab2a5a - ../../devices/virtual/net/vethfab2a5a rootdocker-host:~#总之Docker 通过 Linux 的命名空间实现了网络的隔离进而又通过 iptables 进行了数据包的转发从而实现了 Docker 容器独立和完整的网络功能。需要我把整套 Docker 网络笔记整理成一份完整 markdown 文档吗。
返回列表