最近在公司搭一个测试环境,用 Docker 跑了个服务容器,结果发现容器里 ping 不通百度,curl 外部接口也超时。一开始以为是应用配置问题,折腾半天才发现是网络层面出了状况。这种情况其实挺常见的,特别是刚接触容器网络的人容易踩坑。
检查容器的网络模式
Docker 容器默认使用 bridge 模式,会通过虚拟网桥连接宿主机。如果启动容器时指定了 --network=none,那它就是完全隔离的,自然没法上网。可以用下面命令查看容器网络配置:
docker inspect <容器ID> | grep -i networkmode
正常情况下应该看到 "networkMode": "bridge"。如果是 none,那就得重新启动容器,去掉 --network=none 参数。
宿主机 iptables 规则拦截
有些运维为了安全,默认把 FORWARD 链设成 DROP,这会导致容器流量被阻断。可以临时放开试试:
iptables -P FORWARD ACCEPT
如果这时容器能上网了,说明就是规则问题。建议加上明确的放行策略,比如允许 docker0 网桥的转发:
iptables -A FORWARD -i docker0 -o docker0 -j ACCEPT
iptables -A FORWARD -i docker0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o docker0 -j ACCEPT
DNS 解析失败
有时候能 ping 通 IP 地址,但域名解析不了。这是典型的 DNS 问题。Docker 默认会把宿主机的 /etc/resolv.conf 内容注入容器,但如果宿主机用了 local DNS 缓存(比如 systemd-resolved),可能只监听 127.0.0.53,容器就访问不到。
启动容器时手动指定 DNS 服务器更稳妥:
docker run -d --dns 8.8.8.8 --dns 114.114.114.114 your-image
云服务器安全组或防火墙限制
在阿里云、腾讯云上跑容器,还得看安全组规则。曾经遇到过一次,容器本身没问题,但云平台的安全组没放行出方向流量,导致所有外网请求都被拦下。登录控制台检查一下出站规则,确保允许目标为 0.0.0.0/0 的流量。
IPv4 转发未开启
宿主机如果禁用了 IP 转发,容器的数据包出不去。检查当前状态:
sysctl net.ipv4.ip_forward
如果返回 0,说明没开。临时启用:
sysctl -w net.ipv4.ip_forward=1
要永久生效,修改 /etc/sysctl.conf,把 net.ipv4.ip_forward 设为 1。
这些问题排查下来,基本能解决大多数容器上不了外网的情况。实际处理时可以从最简单的 ping IP 开始,再试域名,逐步缩小范围,比盲目重装省事多了。