容器内解析失败是什么情况
容器里的进程解析域名返回 NXDOMAIN 或超时,表面像网络不通,实际是 DNS 配置问题。容器的 /etc/resolv.conf 在创建时由宿主机生成并快照,若宿主用 systemd-resolved 只监听 127.0.0.53,这个回环地址在容器网络命名空间内不可达,解析必然失败。
基本信息
| 第一步 | docker exec <容器> cat /etc/resolv.conf 看 nameserver 指向 |
|---|---|
| 实测 | nslookup / dig / getent hosts 三选一验证 |
| 自定义网络 | Docker 内置 127.0.0.11 负责解析容器名与服务别名 |
| 覆盖方式 | 单容器用 --dns,全局改 daemon.json 的 dns 字段 |
| 生效时机 | DNS 配置写入发生在创建容器时,改完必须重建容器 |
排查命令
排查命令
docker exec -it myapp cat /etc/resolv.conf # 看 nameserver 指向哪里
docker exec -it myapp getent hosts db # 用系统解析器实测容器名
docker exec -it myapp nslookup example.com # 用 DNS 客户端实测外网域名
docker run -d --dns 223.5.5.5 --dns 119.29.29.29 --name app myapp:1.2.3
docker run --rm --network mynet nicolaka/netshoot dig +short db # 独立容器交叉验证现象与根因对照
| 现象 | 根因 | 处置 |
|---|---|---|
| nameserver 是 127.0.0.53 | 宿主用 systemd-resolved,容器访问不到回环地址 | daemon.json 配真实上游 DNS 后重建 |
| 外网域名可解析、容器名不行 | 两个容器不在同一个自定义网络 | 加入同一 network 或 connect 到同一网络 |
| 解析慢且间歇失败 | 上游 DNS 抖动或 timeout 过短 | 换内网 DNS,检查 resolv.conf 的 options |
| 全部解析失败 | 宿主 DNS 不可用或被拦 53 端口 | 直连 DNS 用 nc -vzu <地址> 53 验证 |
典型使用场景
- 容器内 curl 报 Name or service not known,先分清是解析还是链路问题
- 微服务容器之间用服务名互访,依赖自定义网络的内置 DNS
- 服务从宿主机搬进容器后 HTTP 客户端超时,宿主 resolv.conf 只给了回环地址
- 企业内网域名在容器里解析不到,需要显式指定内网 DNS 服务器
systemd-resolved 的宿主上,最省事的做法是在 /etc/docker/daemon.json 写 dns 数组指向真实上游,再 systemctl reload docker;只改宿主的 resolv.conf 不够,容器里那份是启动时的快照。
用 ping 判断网络容易误判:目标禁 ICMP 或不回 ICMP 时 ping 不通但 TCP 正常,测连通性请用 nc -vz 主机 端口 或 curl -m 5。
docker compose 支持按服务指定 DNS:在服务下写 dns 列表即等价于 docker run --dns,覆盖全局配置;如果只是要让容器之间用服务名互访,把两者放进同一个自定义网络就够了,不必额外配 DNS。