Docker启动报错-iptables failed问题解析与处理
剖析Docker与nftables冲突的根源
一、Bug出现
某天,docker容器运行异常,日志中出现Failed to resolve 'www.baidu.com'的错误,也许是容器内的DNS解析配置问题。
二、寻找线索
2.1 逐步排查
想起该服务器刚安装了fail2ban以防被暴力破解,并启动了nftables作为防火墙。将以上两个服务关闭,接着修改docker-compose.yml,指定DNS地址,执行docker compose up -d进行更新容器,但报出了以下异常:
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint {container_name} (c7d6d789c8164855cc0b99cdb91af8a21587284d7f316752baada0b7315fb9be): Unable to enable DNAT rule: (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8080 -j DNAT --to-destination 172.19.0.6:8080 ! -i br-da87abf7e60c: iptables: No chain/target/match by that name.
(exit status 1))可看到末尾 iptables: No chain/target/match by that name ,通常意味着 Docker 在尝试配置网络(比如设置端口映射)时,发现系统防火墙 (iptables) 的规则链丢失或损坏了。这通常发生在重启了系统防火墙、或者系统上 iptables 与 nftables 有冲突的情况下。
2.2 原因分析
- 问题本质:
Docker默认使用iptables来管理容器网络,它并不直接支持nftables。当安装nftables后,系统很可能将默认的防火墙后端切换到了nftables,导致Docker找不到它所需的传统iptables链,从而报错。
- 检查
iptables中Docker链是否存在
# 查看 nat 表中是否有 DOCKER 链
sudo iptables -t nat -L | grep -i docker
# 查看 filter 表中是否有 DOCKER 链
sudo iptables -t filter -L | grep -i docker如果命令没有输出,说明链丢失了。
2.3 如何解决
🛠️ 方案一:让Docker通过兼容层使用nftables(推荐)
可以让系统通过一个兼容层(iptables-nft),无需卸载nftables,将Docker的iptables指令“翻译”给nftables执行。
操作步骤如下:
- 检查当前iptables模式:确认系统是否正在使用
nftables作为后端。
sudo iptables --version输出中如果包含nf_tables,例如iptables v1.8.10 (nf_tables),说明已经处于兼容模式。但为了确保Docker正常工作,可以强制指定使用iptables-nft。
- 切换iptables到nft后端:使用
update-alternatives命令,将系统的iptables切换为使用nftables后端的版本。
sudo update-alternatives --set iptables /usr/sbin/iptables-nft
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-nft- 重启Docker服务:让Docker重新初始化网络,并自动通过新的兼容层在
nftables中创建所需的规则。
sudo systemctl restart docker🛠️ 方案二:彻底禁用Docker的iptables管理(备选)
如果希望由自己通过nftables来管理服务器的防火墙规则, 不希望Docker自动干预,可以选择这个方案,会关闭Docker自动操作防火墙的能力。
# 编辑daemon.json文件
sudo tee /etc/docker/daemon.json <<EOF
{
"iptables": false
}
EOF
# 重启Docker服务
sudo systemctl restart docker⚠️手动配置 nftables(如果需要):采用此方案后,Docker 容器的端口映射 (-p 参数) 将不会自动工作。需要手动编写 nftables 规则来实现端口转发和网络地址转换(NAT)。这是一个更高级的选项,需要对 nftables 有较深的了解 。
三、验证
- 再次尝试更新容器:
docker compose up -d - 查看
nftables的规则集,应该可以看到Docker自动创建的ip filter和ip nat等表。
sudo nft list ruleset在输出中,应该能找到 chain DOCKER 和 chain DOCKER-USER 等内容 。