容器间网络不通,Compose service name无法解析DNS怎么排查?

文章导读
遇到容器间网络不通,Compose service name 无法解析 DNS,我一般不会急着改配置,而是先按下面这个顺序排除问题。
📋 目录
  1. 先确认故障范围,别急着改配置
  2. 检查 Compose 网络声明,这是最常见的遗漏点
  3. 在容器内验证 DNS 解析,不要依赖 ping
  4. 应用层监听和启动顺序的影响
  5. 资源耗尽和 Docker 内部 DNS 的异常
  6. 整体处理顺序和回滚边界
A A

遇到容器间网络不通,Compose service name 无法解析 DNS,我一般不会急着改配置,而是先按下面这个顺序排除问题。

先确认故障范围,别急着改配置

先区分是全部容器间都不通,还是只有特定 service name 解析失败。在故障容器内执行 docker exec cat /etc/resolv.conf,查看 DNS 指向是否为 127.0.0.11,这是 Docker 内置 DNS 的标准地址。如果指向外部 DNS,说明容器被自定义 network 或 docker-compose.yml 中的 dns 配置覆盖,name 解析自然失效。

这一步能快速把问题分成两类。所有容器互访都失败,多与 Docker 网络栈或宿主机路由有关;只有某个 service name 解析失败,则更可能出在 Compose 配置或服务注册环节。如果 /etc/resolv.conf 里的 DNS 不是 127.0.0.11,先看 compose 文件里是否有 dns 字段,或者服务是否加入了 host 网络。

检查 Compose 网络声明,这是最常见的遗漏点

检查 docker-compose.yml 是否显式声明了 networks,且各服务是否加入到同一个自定义网络。默认情况下 Compose 会创建一个项目级网络,但如果手动指定了不同网络,服务间就无法通过 service name 互访。执行 docker network ls 和 docker network inspect ,确认故障容器是否在同一网络内,这是最常见的遗漏点。

容器间网络不通,Compose service name无法解析DNS怎么排查?

具体看的时候,先 docker network ls 找到项目网络名称,再用 docker network inspect <网络名> 查看 Containers 字段,里面会列出所有挂在该网络下的容器。如果目标服务不在列表里,那就是网络没加对。另外,depends_on 只影响启动顺序,不会帮你把服务加入同一个网络。

这里也顺便给出一个检查命令的示例:

docker network ls
docker network inspect <network_name>

在容器内验证 DNS 解析,不要依赖 ping

在容器内用 getent hosts 或 nslookup 测试解析,注意不要依赖 ping,因为 ICMP 可能被禁用。如果解析返回多个 IP,查看是否包含已停止的旧容器地址。若解析结果为空,再检查目标服务是否实际运行,例如 docker ps 中该服务容器是否处于退出或重启状态,目标服务未运行也会导致 DNS 记录不存在。

我常用的是 getent hosts ,它直接读系统解析器,和 Docker DNS 的交互更真实。如果返回的 IP 和 docker inspect 里的一致,说明解析没问题;如果不一致,比如有旧 IP,可能是容器重启过,需要看容器的启动时间和重启策略。

容器间网络不通,Compose service name无法解析DNS怎么排查?
docker exec <source_container> getent hosts <target_service>

应用层监听和启动顺序的影响

在确认 DNS 能返回正确 IP 后,如果还是连不通,就要继续看链路。在源容器内尝试 ping 目标 IP,再 telnet 目标端口。这时需要重点确认目标服务有没有监听在 0.0.0.0 上。很多常见的应用默认绑定 127.0.0.1,只允许本机访问,跨容器自然会连接拒绝。另外,network_mode: host 会让容器跳过 Docker 内置 DNS 注册,service name 不会解析到它,只能通过宿主机 IP 访问。

启动顺序也会干扰连接。尤其当依赖服务启动失败、Docker 自动重启后,DNS 记录可能短暂指向重启前的旧容器。其他容器如果缓存了过期 IP,就会出现间歇性不通。此时可以在 compose 文件里给依赖方加 depends_on 条件,再配合 healthcheck 确保依赖真正就绪。注意这不能替代网络连通性配置。

资源耗尽和 Docker 内部 DNS 的异常

如果前面几步都正常,但解析依然抖动或失败,就要考虑 Docker 内置 DNS 是否因资源问题而异常。先在宿主机上检查磁盘空间,尤其是 /var/lib/docker 分区是否快满。运行 docker system df 可以看到 overlay2 的使用量,日志或缓存写满都会影响 DNS 相关容器。还有大量容器频繁重建,可能让 Docker 网络栈内部出现端口冲突,这种情况重启 docker 服务通常能恢复,但会中断所有运行中的容器,需要先做好备份或通知相关方。

容器间网络不通,Compose service name无法解析DNS怎么排查?

我一般会先用 df -h /var/lib/docker 和 docker system df 看趋势,再决定是否清理。清理时优先用 docker image prune 清理悬空镜像,不要直接删目录。如果必须重启 docker,先记录当前容器列表,方便之后核对启动情况。

整体处理顺序和回滚边界

整个排查过程,我的操作顺序是:先看 resolv.conf,再查 network 声明,然后测 DNS 解析,继续查应用监听,最后才考虑资源问题。每一步都只改一个变量,并且改之前先备份 compose 文件。比如用 cp docker-compose.yml docker-compose.yml.bak。

修改 networks 或 dns 配置后,需要 docker compose down 再 up 才能让网络重建生效,只执行 restart 不一定能更新 DNS 记录。回滚时恢复备份文件,再执行一次 down 和 up。注意 down 会删除容器,但通常不会删数据卷,除非你显式加了 -v。整个排查过程中尽量不要运行 docker system prune,避免误删必要资源。