Docker端口映射本质是iptables nat表的DNAT和SNAT规则:PREROUTING链做目标地址转换(如8080→172.17.0.2:80),POSTROUTING链用MASQUERADE伪装容器源IP,DOCKER链集中管理各映射规则,并通过!docker0 docker0条件避免回环干扰。
docker 启动容器时用 -p 做端口映射,本质上就是靠 iptables 的 nat 表自动添加 dnat 和 snat 规则。要查看这些底层转发规则,关键不是查 filter 表,而是聚焦在 nat 表的特定链上。
看 PREROUTING 链:查外部访问如何被重定向到容器
这是最核心的一环。当外部请求打到宿主机某个端口(比如 `0.0.0.0:8080`),Docker 就靠这条链做目标地址转换(DNAT),把目标 IP 改成容器 IP、端口改成容器内部端口。运行命令:
sudo iptables -t nat -nvL PREROUTING
你会看到类似这样的规则:
DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80
说明:所有发往本机 8080 端口的 TCP 流量,都被 DNAT 到容器 `172.17.0.2:80`。
看 POSTROUTING 链:查容器返回流量如何伪装回宿主机 IP
容器响应客户端时,源 IP 是自己的私有地址(如 `172.17.0.2`),客户端无法直接识别。Docker 在这里用 MASQUERADE(一种动态 SNAT)把源地址替换成宿主机 IP,确保响应能原路返回。运行命令:
sudo iptables -t nat -nvL POSTROUTING
典型输出中会包含:
MASQUERADE all -- * * 172.17.0.0/16 0.0.0.0/0
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
这表示:来自 Docker 默认网段 `172.17.0.0/16` 的出向流量,全部做源地址伪装。
看 DOCKER 链:Docker 自建的专用子链
Docker 不直接往系统默认链里堆规则,而是创建一个叫 `DOCKER` 的自定义链,并在 `PREROUTING` 和 `OUTPUT` 中跳转过去。这样便于集中管理、避免冲突。查看该链内容:
sudo iptables -t nat -nvL DOCKER
你通常会看到多条 DNAT 规则,每一条对应一个 `-p` 映射,例如:
- DNAT tcp -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 to:172.17.0.3:443
- DNAT tcp -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 tcp dpt:8086 to:172.17.0.2:8086
注意 `!docker0 docker0` 的匹配条件:表示“从非 docker0 接口进、往 docker0 接口出”的包才走这条 DNAT,防止本地回环干扰。
补充:快速定位某端口对应的规则
如果只想确认某个宿主机端口(如 8080)有没有被映射,可以用 grep 精准过滤:sudo iptables -t nat -nvL PREROUTING | grep :8080
sudo iptables -t nat -nvL DOCKER | grep :8080
有输出就说明该端口已配置映射;没输出则可能未映射,或映射的是 UDP(需加 `-p udp` 单独查)。

















