冲突本质是firewalld与docker争夺iptables管理权:firewalld重启清空docker链致端口映射失效(本地通、外部超时);排查三步法:curl localhost验证服务、局域网访问测转发、iptables -t nat -l docker查链是否存在。

iptables 与 Docker 的冲突本质是规则管理权争夺:Docker 自动写入的 DOCKER、DOCKER-USER 等链,常被 firewalld 重启时清空,导致端口映射失效(本地能访问,外部超时)或容器无法出网。排查要快准狠,解决要稳且可持续。
快速确认是不是 iptables-docker 冲突
别急着改配置,先用三步验证:
- 在宿主机执行 curl http://localhost:映射端口 —— 成功说明容器服务正常,问题不在应用层
- 从局域网另一台机器访问 http://[宿主机IP]:映射端口 —— 超时或 Connection refused,基本锁定为转发/防火墙层阻断
- 运行 iptables -t nat -L DOCKER —— 若提示 “No chain/target/match by that name”,说明 Docker 规则已被 firewalld 清除,冲突成立
优先推荐:把 docker0 接口划进专用 zone
适用于 Docker ≥ 20.10.0 + 默认 firewalld 配置(CentOS 7/8、RHEL 8+、Fedora),无需禁用任何服务,兼容性好:
- 将 docker0 网桥移入 docker zone:firewall-cmd --permanent --zone=docker --add-interface=docker0
- 启用地址伪装(必须!否则容器无法访问外网):firewall-cmd --permanent --zone=docker --add-masquerade
- 重载生效:firewall-cmd --reload
- 验证是否生效:firewall-cmd --get-active-zones 应显示 docker 区域及 docker0 接口
更彻底方案:交由 firewalld 统一管 iptables
让 Docker 完全退出 iptables 管理,只负责容器内部网络,适合对防火墙策略有集中管控需求的生产环境:
- 编辑 /etc/docker/daemon.json(不存在则新建),加入:{"iptables": false}
- 重启 Docker:systemctl restart docker
- 开启全局 masquerade(关键!否则容器出向失败):firewall-cmd --add-masquerade --permanent && firewall-cmd --reload
- 手动放行业务端口,例如:firewall-cmd --add-port=8080/tcp --permanent && firewall-cmd --reload
自定义规则该加在哪条链?
避免被 Docker 覆盖,位置比内容更重要:
- 想控制“进容器的流量”(如限制某 IP 访问所有容器)→ 加到 DOCKER-USER 链(Docker 所有自动规则之前):
iptables -I DOCKER-USER -s 192.168.10.5 -j DROP - 想控制“访问宿主机自身服务”(如 curl localhost:8080)→ 加到 INPUT 链,但注意匹配接口(如 -i docker0 或 -i lo)
- 绝对不要直接改 DOCKER 链 —— 这是 Docker 自己维护的,重启后会被重置
- 规则持久化:Debian/Ubuntu 用 iptables-save > /etc/iptables/rules.v4;CentOS/RHEL 用 iptables-save > /etc/sysconfig/iptables,并确保开机加载











