欢迎光临
专业的主机评测网站

Docker容器无法联网怎么办?DNS解析失败与网络故障排查教程

部署Docker应用时,有时会遇到这样的情况:服务器本身可以访问网站,但容器内的软件无法下载文件、连接接口,日志反复出现域名解析失败或连接超时。

这类问题可能发生在DNS、容器路由、宿主机转发规则,也可能只是应用配置错误。排查时,可以先确认连接在哪一层失败,再修改对应配置。

Docker容器无法联网的DNS、路由与转发排查教程

本文适用于Linux服务器上的常规Docker Engine,重点检查使用bridge网络的容器及其IPv4出站连接。Docker Desktop、Rootless Docker和Kubernetes需要结合各自网络机制处理。

一、确认容器状态和宿主机连接

以下命令在Docker所在的宿主机上执行,以root权限为例。先查看正在运行的容器:

docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Networks}}'

将下面的my-app替换成实际容器名称:

container='my-app'

docker inspect -f \
  '状态={{.State.Status}} 网络模式={{.HostConfig.NetworkMode}}' \
  "$container"

如果容器不断重启,应先排查启动失败。如果网络模式为none,说明它没有接入常规容器网络,需要检查部署配置。

接下来选择一个需要访问的HTTPS域名。下面使用示例域名,实际排查时应替换成发生故障的接口域名:

target_host='example.com'

curl -q -4 --noproxy '*' \
  --connect-timeout 5 --max-time 15 \
  -I "https://$target_host/"

这里使用IPv4,并排除代理环境变量的影响,测试的是直连能力。如果你的网络必须通过代理访问目标,需要另外检查代理连接。

收到HTTP响应,说明已经连接到目标服务;即使状态码是403或405,也不能直接判断为网络不通。

二、固定目标IP,区分DNS故障与网络故障

直接比较两个环境的域名访问结果,可能受到DNS返回不同地址的影响。更准确的方法,是让宿主机和容器访问同一个目标IP。

先获取目标域名的一个IPv4地址:

target_ip=$(getent ahostsv4 "$target_host" | awk 'NR==1 {print $1}')
printf '目标IPv4:%s\n' "$target_ip"

如果没有输出有效地址,先检查宿主机的域名解析,不要继续执行后面的固定IP测试。

获取容器进程PID:

container_pid=$(docker inspect -f '{{.State.Pid}}' "$container")
printf '容器PID:%s\n' "$container_pid"

确认PID大于0,且容器没有持续重启。容器重启或重建后,需要重新获取PID。

先从宿主机测试指定IP:

curl -q -4 --noproxy '*' \
  --connect-timeout 5 --max-time 15 \
  --resolve "$target_host:443:$target_ip" \
  -I "https://$target_host/"

再进入容器的网络命名空间,测试相同目标:

nsenter -t "$container_pid" -n -- \
  curl -q -4 --noproxy '*' \
  --connect-timeout 5 --max-time 15 \
  --resolve "$target_host:443:$target_ip" \
  -I "https://$target_host/"

--resolve临时指定连接地址,同时保留HTTPS请求的域名和证书校验。

这条nsenter命令使用宿主机的curl,经过容器的网络环境发起连接,因此容器镜像没有安装curl也能检查。不过,它不会复制应用自身的代理、证书库和运行配置。

测试情况下一步检查方向
宿主机固定IP测试也失败宿主机出口、目标服务或中间网络
宿主机成功,容器网络环境失败容器路由、宿主机转发和防火墙
容器固定IP测试成功,但域名查询失败DNS配置及DNS请求路径
网络与DNS测试均正常,应用仍失败应用代理、证书、请求配置及实际使用的IP协议

宿主机需要安装curl、ip、nsenter和后续使用的dig。Debian、Ubuntu缺少工具时,可安装:

apt-get update &&
apt-get install -y curl iproute2 util-linux dnsutils

三、检查容器DNS,并为单个服务配置解析服务器

先读取容器的DNS配置:

docker cp -L "$container":/etc/resolv.conf - | tar -xO

该方法不依赖容器内部的cat命令。

如果看到:

nameserver 127.0.0.11

通常属于正常情况。连接到自定义Docker网络的容器会使用Docker内置DNS,再由它处理外部域名查询。

将下面的地址替换成刚才看到的nameserver地址:

resolver_ip='127.0.0.11'

nsenter -t "$container_pid" -n -- \
  dig @"$resolver_ip" "$target_host" A +time=3 +tries=1

观察查询结果:

  • 返回预期的A记录:本次DNS查询成功。
  • 查询超时:继续检查DNS服务器可达性及相关防火墙规则。
  • 返回NXDOMAIN:表示解析服务器认为域名不存在,需要核对域名及解析配置。
  • 返回SERVFAIL:需要进一步检查解析服务器或其上游处理情况。

这里必须显式指定DNS服务器。只使用nsenter -n运行普通域名查询,仍可能读取宿主机的解析配置,导致判断失真。

如果怀疑原有DNS不可用,可以在相同网络环境中测试另一台允许使用的DNS服务器。例如:

nsenter -t "$container_pid" -n -- \
  dig @1.1.1.1 "$target_host" A +time=3 +tries=1

1.1.1.1仅作为示例,应选择实际网络中可达、符合业务需要的DNS。需要解析企业内部域名时,应保留相应的内部解析能力。

确认替代DNS有效后,可在Compose中为发生问题的服务添加配置:

services:
  app:
    dns:
      - "1.1.1.1"

这是配置片段,需要合并到原有服务中,保留原来的镜像、端口和数据卷等配置。

在原项目目录执行,app替换成实际的Compose服务名:

docker compose config -q &&
docker compose up -d --no-deps app

如果原来使用了-f或-p参数,这里也要沿用。

修改DNS后,Compose会重建对应服务,造成短暂中断。执行前确认数据已经持久化,依赖服务处于运行状态。

重建后,容器的resolv.conf仍可能显示127.0.0.11,这不代表配置没有生效。应重新查询目标域名,并验证应用请求是否恢复。

四、固定IP仍无法连接时,检查路由和网络配置

如果宿主机能连接目标IP,而容器网络环境不能连接,继续查看容器的IPv4路由:

nsenter -t "$container_pid" -n -- ip -4 route

nsenter -t "$container_pid" -n -- \
  ip -4 route get "$target_ip"

重点观察是否存在可用路由,以及访问目标时实际选择的接口和网关。

列出容器连接的网络:

docker inspect -f \
  '{{range $name, $conf := .NetworkSettings.Networks}}{{println $name}}{{end}}' \
  "$container"

将下面的网络名称替换为实际值:

network='myproject_default'

docker network inspect "$network" --format \
  '驱动={{.Driver}} 内部网络={{.Internal}} 地址池={{json .IPAM.Config}}'

主要检查以下情况:

  • 容器是否只连接到Internal=true的隔离网络。
  • 容器连接多个网络后,实际出口是否符合预期。
  • Docker网段是否与宿主机的局域网、VPN或业务网段重叠。

如果某个服务原本就被设计为仅在内部网络运行,需要先确认它是否应该访问外网,再调整Compose中的网络连接。

五、检查宿主机IPv4转发和防火墙

常规bridge网络访问外部网络,需要宿主机进行转发。查看当前设置:

sysctl net.ipv4.ip_forward

如果结果为0,且该主机确实需要承担容器转发,可以在确认现有防火墙限制正确后临时启用:

sysctl -w net.ipv4.ip_forward=1

这项修改影响宿主机的IPv4转发能力。多网卡主机还需要限制不应互通的接口,不能仅开启转发而忽略访问控制。

确认问题因此解决后,再将以下配置写入系统的持久化sysctl配置,并检查是否有其他配置将其覆盖:

net.ipv4.ip_forward = 1

如果转发已经启用,继续检查防火墙。

Docker使用iptables后端时,可以查看:

iptables -nvL FORWARD
iptables -nvL DOCKER-USER
iptables -t nat -S

重新发起一次失败请求,结合规则顺序和计数器判断是否命中了丢弃规则。

FORWARD默认策略为DROP,不等于Docker网络一定有问题。 正常配置也可能采用这一策略,再通过具体规则允许容器流量。

如果Docker明确配置了原生nftables后端,应查看:

nft list ruleset

原生nftables后端不创建同名的DOCKER-USER链,不能仅凭找不到该链判断规则损坏。

若此前在Docker守护进程配置中设置了"iptables": false,同时又没有配置替代的转发和NAT规则,也可能导致容器无法出网。此时需要恢复正确的规则管理方式。

不要通过清空全部防火墙规则来修复,这会同时破坏其他服务的访问控制。涉及Docker守护进程配置的调整,应安排维护窗口处理。

六、回到实际业务验证

完成修改后,重新获取容器PID,再执行固定IP测试和DNS查询。

随后重新触发原来失败的业务操作,并查看近期日志:

docker logs --since 5m --tail 100 "$container"

如果网络测试正常,应用仍然失败,应继续核对应用使用的代理地址、CA证书、目标端口,以及是否优先使用了不可达的IPv6路径。

另外,ping不通只能说明ICMP测试没有成功;镜像拉取成功也只能证明Docker守护进程具备相应访问能力。最终应以应用实际需要的域名、端口和请求是否恢复作为验证依据。

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。

专业的主机评测网站

国内/国外VPS测评、云服务器评测,从VPS或IDC商家的资质、客服水平、售后服务、VPS线路、服务器硬件、主机性能等、访问速度进行云主机、IDC测评。

联系我们联系我们