🐳 Docker 容器断网排查“四步走”指南
当你的 Docker 容器突然无法访问公网(比如调不通外部 API、发不出请求),请不要慌,按照以下由浅入深的步骤像老中医一样“望闻问切”:
第一步:确认“宿主机”本身的网络(排除大环境问题)
容器的网络是寄生在宿主机上的。如果宿主机自己都断网了,容器肯定也出不去。
操作:在宿主机执行
curl -I [https://www.baidu.com](https://www.baidu.com)
- ✅ 返回 200:宿主机网络正常,问题出在 Docker 或防火墙。进入第二步。
- ❌ 超时或报错:服务器本身断网了(检查云服务器安全组、欠费情况、物理网线等)。
第二步:给容器做“网络全身 CT”(辨别症状)
我们需要知道容器到底是解析不了域名,还是数据包发不出去。
操作:在容器内执行(或通过 docker exec)
# 1. 测 DNS(域名解析)
ping -c 2 baidu.com
# 2. 测纯 IP(绕过 DNS)
curl -I -m 5 [http://110.242.68.3](http://110.242.68.3) # 百度的纯 IPv4 地址
根据症状诊断:
-
DNS 报错 (
bad address/Name or service not known),但纯 IP 能通:- 病因:容器的 DNS 配置坏了。
- 解法:修改宿主机
/etc/docker/daemon.json,加入"dns": ["8.8.8.8", "114.114.114.114"],然后重启 Docker。
-
报错
Network is unreachable(网络不可达):- 病因:容器没有去往公网的路由,或者踩了IPv6 陷阱(代码试图用 IPv6 访问,但容器只配了 IPv4)。
-
报错
Timeout(连接超时):- 病因:数据包发出去了,但在半路被宿主机的防火墙(iptables/ufw)拦截并丢弃了。
第三步:检查宿主机的“转发开关”(最常见的低级错误)
Docker 容器把数据包发给宿主机,宿主机需要把它“转发”到公网。如果内核没开转发,包就死在宿主机了。
操作:在宿主机执行
cat /proc/sys/net/ipv4/ip_forward
-
✅ 输出 1:正常,进入第四步。
-
❌ 输出 0:内核禁用了转发。
- 解法:执行
sudo sysctl -w net.ipv4.ip_forward=1。要永久生效,写入/etc/sysctl.conf。
- 解法:执行
第四步:核查防火墙(终极 Boss)
如果前三步都没问题,那 99% 是宿主机的防火墙(UFW / Firewalld / iptables)在捣乱,它们经常和 Docker 抢夺网络控制权。
操作:检查 iptables 的 FORWARD 链
sudo iptables -nL FORWARD
- 如果看到第一行是
policy DROP且没有明确放行 Docker 的规则,或者有ufw-reject相关的拦截字眼,说明数据包被防火墙“暗杀”了。
☢️ 终极核弹疗法:一键网络重置脚本
如果你不想一步步查防火墙规则,或者像这次一样遇到 UFW 损坏的奇葩情况,直接在宿主机运行这个**“网络洗髓脚本”**。
它的作用:保护 SSH 不断开 -> 清除所有垃圾拦截规则 -> 关掉捣乱的防火墙 -> 让 Docker 重新铺设干净的网络。
echo "=== 1. 保护连接 ===" && \
sudo iptables -P INPUT ACCEPT && \
sudo iptables -P FORWARD ACCEPT && \
sudo iptables -P OUTPUT ACCEPT && \
echo "=== 2. 清理残留规则 ===" && \
sudo iptables -F && \
sudo iptables -X && \
sudo iptables -t nat -F && \
sudo iptables -t nat -X && \
echo "=== 3. 禁用冲突的 UFW 防火墙 ===" && \
sudo systemctl stop ufw 2>/dev/null || true && \
sudo systemctl disable ufw 2>/dev/null || true && \
echo "=== 4. 重启 Docker 重建网络 ===" && \
sudo systemctl restart docker && \
echo "✅ 修复完成!"
(注:云服务器推荐依赖云厂商自带的“安全组”进行端口防护,服务器内部尽量不要开 UFW/Firewalld,这能避免 90% 的 Docker 网络玄学问题。)