Docker容器映射端口到主机的原理
前置知识 #
iptables:捕获并控制容器和主机之间的流量, 可以通过iptables -t nat -nL命令查看iptables的(S/D)NAT规则 docker0:虚拟交换机 veth1b62ff4@if56:虚拟交换机的虚拟接口 上下两个虚拟接口成对出现 eth0@if57:容器的虚拟接口
网络环境 #
CentOS:ens33->192.168.40.180/24、docker0->172.17.0.1/16、veth1b62ff4@if56 CentOS的容器:eth0@if57->172.17.0.2/16(gateway:172.17.0.1) Windows11:VMnet8->192.168.40.1/24
假设CentOS的容器有一个8080/tcp的web服务映射到了CentOS的80/tcp #
这个时候Windows11通过浏览器去访问http://192.168.40.180:80, CentOS的ens33接口接收到这个数据包后, iptables的DNAT规则会在数据包被路由之前修改数据包的目的地址和目的端口为172.17.0.2:8080,修改完成后, 数据包会被路由到docker0虚拟机交换机, 虚拟交换机会把数据包发送到veth1b62ff4@if56虚拟接口, CentOS的容器上的eth0@if57虚拟接口就会接收到数据包并通过eth0@if57虚拟接口发送回复数据包, CentOS的docker0交换机通过veth1b62ff4@if56虚拟接口接收到这个数据包后, iptables的DNAT规则会在数据包被路由之前修改数据包的源地址和源端口为192.168.40.180:80, 修改完成后,数据包通过路由就会从CentOS的ens33接口发送出去, 最后Windows11的VMnet8接口接收到数据包会交给浏览器处理。 下面是一个简单的表达: win11浏览器访问http://192.168.40.180:80(192.168.40.1:12345->192.168.40.180:80) –> win11-VMnet8 –> CentOS-ens33 –> CentOS-iptables-DNAT-修改数据包为192.168.40.1:12345->172.17.0.2:8080 –> CenOS-docker0 –> CentOS-veth1b62ff4@if56 –> CentOS的容器-eth0@if57 –> CentOS的容器-服务(172.17.0.2:8080->192.168.40.1:12345) –> CentOS的容器-eth0@if57 –> CentOS-veth1b62ff4@if56 –> CenOS-docker0 –> CentOS-iptables-DNAT-修改数据包为192.168.40.180:80->192.168.40.1:12345 –> CentOS-ens33 –> win11-VMnet8 –> win11浏览器处理 示意图: Docker容器映射端口到主机.excalidraw
查看iptables的DNAT规则和SNAT规则 #
[root@xianchaomaster1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 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 -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
可以看到DNAT规则, 为什么没有SNAT规则? #
MASQUERADE 是 SNAT 的一种特殊形式,通常在动态网络环境下(如容器或虚拟机)使用。MASQUERADE 自动将源 IP 地址修改为出站接口的 IP 地址,而不需要手动指定静态 IP,因此它通常比传统的 SNAT 更常用。