Docker容器无法访问外网怎么办?DNS解析、默认网关与防火墙排查教程

Docker容器启动正常却无法访问外网,问题可能出在DNS、路由、IP转发、NAT或防火墙。本文提供一套从宿主机到容器、从解析到链路的完整排查流程,并说明生产环境中应避免的高风险操作。

Docker 容器启动正常,端口也能映射,但在容器内执行 curl、拉取依赖或连接第三方 API 时一直超时,这是服务器运维中很常见的一类问题。它看起来像“容器断网”,实际可能发生在 DNS 解析、容器路由、Docker 网桥、主机转发、防火墙或上游网络中的任意一层。

排查这类故障,最重要的是先把“域名解析失败”和“IP 链路不通”分开。不要一开始就重启 Docker、关闭防火墙或删除全部网络,这些操作既可能扩大影响,也容易掩盖真正原因。

Docker容器无法访问外网怎么办?DNS解析、默认网关与防火墙排查教程

一、先确认故障范围

先在宿主机测试外网和 DNS:

curl -I --connect-timeout 5 https://www.example.com
getent hosts www.example.com

再进入故障容器执行相同测试:

docker exec -it <容器名或ID> sh

容器镜像中如果有 curlgetentping,可以依次检查:

cat /etc/resolv.conf
ip route
getent hosts www.example.com
curl -I --connect-timeout 5 https://www.example.com

精简镜像可能没有这些工具。不要为了测试直接修改生产容器,可以启动一个临时排障容器,并让它加入相同网络:

docker run --rm -it --network <网络名> nicolaka/netshoot

根据结果,故障通常可以先分为四类:

现象 优先检查方向
宿主机和容器都不能访问外网 云平台安全策略、宿主机路由、上游网络
宿主机正常,所有容器都不通 Docker 转发、NAT、防火墙、daemon 配置
只有一个容器或一个网络不通 容器网络模式、自定义网络、默认网关
IP 可以访问,域名不能解析 /etc/resolv.conf、Docker DNS、上游 DNS

二、区分 DNS 故障和网络不通

先尝试访问一个已知 IP,再测试域名。不同环境可能禁止 ICMP,因此 ping 失败不能单独证明网络中断,更可靠的办法是测试 TCP 连接:

curl -I --connect-timeout 5 http://1.1.1.1
getent hosts www.example.com

如果 IP 能连接而域名解析失败,重点查看容器中的 DNS 配置:

cat /etc/resolv.conf

使用默认 bridge 网络时,容器通常会获得宿主机 DNS 配置的副本;使用用户自定义网络时,Docker 会提供内置 DNS,并把外部查询转发给宿主机配置的 DNS 服务器。因此,宿主机的 /etc/resolv.conf、本地 DNS 服务或企业内网 DNS 出现异常,都可能传递到容器。

可以先为单个容器临时指定 DNS 验证判断:

docker run --rm --dns 1.1.1.1 alpine nslookup www.example.com

如果临时指定 DNS 后恢复,再考虑为 Docker daemon 配置稳定的 DNS。编辑前先备份 /etc/docker/daemon.json,并确保它是合法 JSON:

{
  "dns": ["1.1.1.1", "8.8.8.8"]
}

验证配置后再重启 Docker:

dockerd --validate --config-file=/etc/docker/daemon.json
systemctl restart docker

重启 Docker 可能影响正在运行的业务容器,应安排维护窗口。企业内网环境还要确认公共 DNS 是否能够解析内部域名,不要直接用公共 DNS 覆盖公司 DNS。

三、检查容器网络模式和默认网关

查看容器使用的网络模式、IP 地址和网关:

docker inspect <容器名或ID>
docker network inspect <网络名>

重点关注 NetworkModeIPAddressGateway 和容器连接的网络名称。容器内也可以检查路由:

ip addr
ip route

正常情况下应存在一条默认路由,例如:

default via 172.18.0.1 dev eth0

常见问题包括:

  • 容器被配置为 network_mode: none,本身就不会获得外网连接。
  • 自定义网络与宿主机、VPN 或其他 Docker 网络的网段冲突。
  • 容器同时加入多个网络,错误的默认网关被选中。
  • Compose 文件调整后只重启了进程,没有重新创建容器,旧网络配置仍在使用。
  • 使用 macvlanipvlan 或自定义路由时,上游交换机和路由器没有对应配置。

如果确认是网络配置问题,可以在评估影响后重新创建容器,而不是直接删除整个 Docker 网络:

docker compose up -d --force-recreate <服务名>

四、检查宿主机是否允许 IP 转发

Docker 的桥接网络需要宿主机在不同网络接口之间转发数据。检查 IPv4 转发状态:

sysctl net.ipv4.ip_forward

通常应返回:

net.ipv4.ip_forward = 1

如果该值为 0,要继续确认它为什么被关闭。临时开启可以用于验证:

sysctl -w net.ipv4.ip_forward=1

需要长期生效时,应通过发行版推荐的 sysctl 配置文件管理,而不是只修改运行时值。还要注意,启用转发会改变主机的网络行为,云服务器、VPN 网关或多网卡主机应同步检查安全策略。

五、检查 Docker NAT 和防火墙规则

桥接网络中的容器访问外网,通常依赖宿主机的转发和源地址转换。Docker 会根据网络和端口配置创建相应的防火墙规则;如果安全软件、运维脚本或防火墙重载清除了这些规则,容器可能突然失去外网连接。

先确认 Docker 使用的防火墙后端及现有规则,不要直接执行清空规则的命令:

docker info
iptables -S
iptables -t nat -S
nft list ruleset

如果服务器使用 firewalld,还可以检查:

firewall-cmd --state
firewall-cmd --get-active-zones
firewall-cmd --list-all

重点关注以下情况:

  1. FORWARD 链的默认策略或自定义规则阻止了 Docker 网桥流量。
  2. Docker 的 NAT/MASQUERADE 规则被防火墙重载或第三方脚本覆盖。
  3. DOCKER-USER 链中存在过于宽泛的拒绝规则。
  4. 云安全组、主机防火墙和 Docker 规则叠加后,实际出口被阻断。
  5. 系统从 iptables 切换到 nftables 后,旧脚本仍在操作另一套规则。

不要用 iptables -Fnft flush ruleset 或关闭 firewalld 作为长期解决方案。这类操作可能同时暴露数据库、管理端口和容器服务。更稳妥的做法是先导出规则,定位具体命中链,再添加最小范围的放行策略。

六、检查代理、VPN和云平台出口限制

有些容器可以访问普通网站,却无法访问代码仓库、镜像站或特定 API。这时还要检查:

  • 宿主机是否通过 HTTP/HTTPS 代理出网,而容器没有设置代理变量。
  • VPN 或 WireGuard 是否改写了默认路由、策略路由或 MTU。
  • 云平台是否限制公网出口,或实例本身没有公网 IP、NAT 网关和正确路由。
  • 企业网络是否要求使用内部 DNS、出口代理或白名单。
  • 请求是否因为 IPv6 优先、路径 MTU 或 TLS 检查而超时。

查看容器中的代理变量:

env | grep -i proxy

如果使用 Compose,可以在服务级别明确设置代理,但不要把包含账号密码的代理地址写入公开仓库:

services:
  app:
    environment:
      HTTP_PROXY: http://proxy.example:3128
      HTTPS_PROXY: http://proxy.example:3128
      NO_PROXY: localhost,127.0.0.1,.example.internal

七、按最小影响顺序恢复

完成定位后,建议按以下顺序处理:

  1. 修正单个容器或 Compose 服务的 DNS、网络和代理配置。
  2. 重新创建受影响的单个容器,验证问题是否消失。
  3. 修正宿主机转发、防火墙或 NAT 规则,并保存变更前后的规则快照。
  4. 只有在确认 daemon 配置或 Docker 规则异常时,才安排重启 Docker。
  5. 变更后同时验证 DNS、TCP 连接、业务 API 和容器重启后的持久性。

可以使用下面的简化检查清单复核:

# 宿主机
curl -I --connect-timeout 5 https://www.example.com
sysctl net.ipv4.ip_forward
docker info

# 容器和网络
docker inspect <容器名或ID>
docker network inspect <网络名>
docker exec <容器名或ID> cat /etc/resolv.conf
docker exec <容器名或ID> ip route

总结

Docker 容器无法访问外网,不等于 Docker 服务本身损坏。先比较宿主机和容器的结果,再把 DNS、路由、转发、NAT、防火墙和上游出口逐层拆开,通常能在不影响其他容器的情况下找到原因。

生产环境中最需要避免的是“为了恢复网络,先清空防火墙或重启所有服务”。正确的处理方式应当是保留现场、缩小范围、进行可回滚的最小修改,并在容器重新创建和服务器重启后再次验证。

参考资料

  1. Docker Docs: Networking overview

https://docs.docker.com/engine/network/

  1. Docker Docs: Bridge network driver

https://docs.docker.com/engine/network/drivers/bridge/

  1. Docker Docs: Packet filtering and firewalls

https://docs.docker.com/engine/network/firewall-iptables/

  1. Docker Docs: docker network inspect

https://docs.docker.com/reference/cli/docker/network/inspect/

  1. Docker Docs: Configure the Docker daemon

https://docs.docker.com/engine/daemon/

核验日期:2026年8月25日

Web服务与建站知识库

Nginx出现413 Request Entity Too Large怎么办?上传大小限制与反向代理排查教程

2026-8-24 14:27:33

实操指南知识库

云服务器快照和备份有什么区别?恢复范围、保留策略与容灾选择指南

2026-8-25 16:35:18