Docker 容器无法访问外网?教你排查网络
环境准备:先确认你遇到了哪种无法访问外网的情况
在动手排查前,先确认现象是所有容器都不能访问外网,还是只有特定容器或特定服务(如 apt-get、curl)不能访问。
这能帮你快速缩小范围。
你需要准备一台安装了 Docker 的 Linux 服务器(本文以 Ubuntu 22.04 为例),拥有 root 或 sudo 权限。
第一步:检查容器网络模式与 DNS 解析
很多新手遇到的“无法访问外网”其实是 DNS 解析失败。
执行以下命令进入一个测试容器:
docker run -it --rm alpine sh
在容器内部执行:
ping -c 4 8.8.8.8
- 如果能 ping 通 IP,说明网络底层没问题,问题出在 DNS。
- 如果 ping 不通,则继续检查宿主机防火墙和 iptables。
检查容器内的 DNS 配置
cat /etc/resolv.conf
默认情况下 Docker 会把宿主机的 /etc/resolv.conf 映射进去。
如果里面只有 127.0.0.53 或 localhost,可能是 systemd-resolved 导致的问题。
解决方法:修改 Docker 启动参数,将 DNS 指向公共 DNS 如 8.8.8.8。
操作路径:修改 /etc/docker/daemon.json,添加:
{
"dns": ["8.8.8.8", "114.114.114.114"]
}
保存后重启 Docker:
sudo systemctl restart docker
第二步:排查宿主防火墙与 iptables 规则
Docker 依赖 iptables(或 nftables)进行网络地址转换(NAT),如果宿主机的防火墙规则禁止了转发或清空了 DOCKER 链,容器就无法访问外网。
检查 iptables FORWARD 链默认策略
sudo iptables -L FORWARD -n
如果看到 Chain FORWARD (policy DROP),说明默认丢弃转发包。
Docker 会在启动时自动添加 ACCEPT 规则,但某些安全软件或手动操作可能覆盖了这些规则。
你可以临时放行:
sudo iptables -P FORWARD ACCEPT
但更推荐使用 iptables-persistent 持久化规则,或者检查是否有防火墙软件(如 firewalld、ufw)拦截。
确认 ufw 是否开启(Ubuntu 常见)
sudo ufw status
如果 ufw 处于 active 状态,需要允许 Docker 的网桥转发:
sudo ufw default allow FORWARD
然后重启 Docker:
sudo systemctl restart docker
第三步:检查 Docker 网络模式与代理设置
Docker 默认使用 bridge 网络模式,如果宿主本身需要通过代理访问外网,容器也需要继承代理变量。
查看当前容器网络模式
docker inspect <容器名> | grep NetworkMode
如果是 host 模式,容器直接使用宿主机网络栈,网络问题往往出现在宿主机本身。
如果是 none 模式,肯定无法访问外网。
设置 Docker 代理(适用于企业内网环境)
在 /etc/systemd/system/docker.service.d/proxy.conf 中写入:
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080"
Environment="HTTPS_PROXY=http://proxy.example.com:8080"
保存后执行:
sudo systemctl daemon-reload
sudo systemctl restart docker
避坑指南:这些操作会破坏容器网络
- 不要随意清空 iptables。很多教程教你
iptables -F,这会清掉 Docker 自动添加的规则,导致容器失联。正确做法是iptables -D删除特定规则。 - 启动容器时加上
–network host不代表一劳永逸。host 模式牺牲了隔离性,生产环境慎用。 - 重启 Docker 后需要重新启动所有容器。如果你用
systemctl restart docker,所有容器都会停止,记得用docker start $(docker ps -aq)批量启动。 - 检查宿主机是否有多块网卡。如果 Docker 绑定了错误网卡,修改
/etc/docker/daemon.json中的bip参数指定网桥网段。
效果验证:确保容器能正常访问外网
用同一个 Alpine 容器测试:
docker run -it --rm alpine sh
# 在容器内执行
wget -q -O- http://example.com
如果返回 HTML 内容,说明网络恢复。
你也可以用 apk add curl 安装 curl 后测试:
curl -I https://www.baidu.com
如果能拿到 HTTP 200,恭喜你,Docker 容器无法访问外网的问题已经解决。
最后建议:把上述排查步骤记在本地,下次遇到类似问题时可以快速复现。
如果你在操作中发现其他意外报错,优先回看避坑指南和高频问题解答部分。