当宿主机可以正常访问网络,而 Docker 容器却出现“域名解析失败”“Temporary failure in name resolution”或服务连接超时时,问题通常集中在 DNS 配置、网络可达性或 Docker 内置解析机制上。本文从现象识别、分层诊断到自定义 DNS 配置,整理一套可直接执行的排查流程,帮助快速定位故障。🔍
一、先判断是不是 DNS 问题
排查时不要直接修改配置,应先区分“网络不通”和“域名无法解析”。进入容器后,分别测试 IP 地址与域名:
docker exec -it 容器名 sh
ping -c 3 1.1.1.1
ping -c 3 example.com
如果 IP 可以访问,而域名无法访问,通常可以将重点放在 DNS。如果两者都失败,则还要检查容器路由、网桥、防火墙、代理、VPN、云安全策略或宿主机转发设置。部分精简镜像没有 ping 命令,可使用 nslookup、getent hosts 或 wget 进行替代测试。
二、检查容器当前 DNS 配置
容器中的 DNS 信息主要记录在 /etc/resolv.conf。执行以下命令查看实际内容:
docker exec 容器名 cat /etc/resolv.conf
使用默认 bridge 网络时,容器通常继承宿主机可用的 DNS 配置;接入用户自定义网络时,可能看到 Docker 内置 DNS 地址 127.0.0.11,它负责解析同一网络中的容器名称,并将其他查询转发给上游服务器。用户自定义网络支持通过容器名互相通信,相关机制可参考 Docker 网络官方说明。
如果文件中出现 127.0.0.1 或其他仅在宿主机本地监听的地址,需要特别注意。在容器内部,127.0.0.1 指向容器自身,并不等于宿主机,因此容器可能无法访问宿主机上的本地 DNS 服务。🧭
三、按照层级定位故障点
- 检查宿主机:确认宿主机能够解析相同域名,并查看宿主机的 /etc/resolv.conf。
- 检查 DNS 端口:确认容器到目标 DNS 服务器的 UDP 53 和必要时的 TCP 53 通信没有被防火墙阻断。
- 检查 Docker 网络:执行 docker network inspect 网络名,核对容器是否加入预期网络、网关是否正确。
- 检查内部域名:企业内网域名通常只能由公司 DNS 解析,不应盲目替换为公共 DNS。
- 检查代理与 VPN:VPN 切换、网络管理服务更新或代理规则变化,可能使 Docker 仍使用旧的上游 DNS。
还可以启动一个临时容器进行对照测试,避免因业务镜像缺少工具或自身配置异常而误判:
docker run --rm busybox nslookup example.com
四、为单个容器指定 DNS
如果只需要验证某个 DNS 是否可用,或仅让特定容器使用专用解析服务器,可以在创建容器时加入 --dns 参数:
docker run --rm --dns 10.0.0.53 --dns 1.1.1.1 busybox nslookup example.com
这种方式影响范围小,适合临时排障和特殊业务。多个 --dns 参数可提供备用服务器,但必须确认容器确实能够访问这些地址。对于内部域名,应优先放置企业 DNS,避免公共 DNS 返回不存在或错误结果。
Docker Compose 配置方式
使用 Compose 时,可在服务下配置 dns、dns_search 和 dns_opt。例如:
services:
app:
image: your-image
dns:
- 10.0.0.53
- 1.1.1.1
dns_search:
- example.internal
修改后应执行 docker compose up -d --force-recreate 重建容器。仅重启旧容器不一定会重新应用已变更的 Compose 配置。
五、配置 Docker 全局 DNS
如果多个容器都存在相同问题,可以在 Linux 宿主机的 /etc/docker/daemon.json 中统一设置 DNS。Docker 官方推荐使用 JSON 配置文件集中管理守护进程选项,默认路径和不同运行模式的差异可参考 Docker 守护进程配置文档。
{
"dns": ["10.0.0.53", "1.1.1.1"],
"dns-search": ["example.internal"]
}
如果 daemon.json 已包含镜像仓库、日志或存储配置,应将 DNS 字段合并到原有 JSON 对象中,不要覆盖其他设置。修改后先校验格式,再重启 Docker:
sudo dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker
sudo systemctl status docker
守护进程配置与启动参数中不要重复设置同一个选项,否则 Docker 可能因配置冲突而无法启动。全局修改还可能中断正在运行的业务容器,因此生产环境应安排维护窗口,并提前确认容器重启策略。⚠️
六、验证修复是否真正生效
- 重新创建测试容器,并再次查看 /etc/resolv.conf。
- 使用 nslookup 或 getent hosts 测试公网域名和内部域名。
- 同时测试容器名称解析,确认自定义网络的服务发现正常。
- 连续执行多次查询,排除单个上游 DNS 间歇性超时。
- 查看 docker logs、journalctl -u docker 和防火墙日志,确认没有新的错误。
不要把直接修改容器内 /etc/resolv.conf 当作长期方案。该文件通常由 Docker 管理,容器重建后可能恢复原状。更可靠的做法是使用 docker run、Compose 或 daemon.json 固化配置,并将相关变更纳入配置管理。
总结
Docker 容器 DNS 异常应遵循“先区分网络与解析,再检查 resolv.conf,最后按容器级或全局级配置”的顺序。单个服务优先使用 --dns 或 Compose,全局问题再考虑 daemon.json;涉及企业内部域名时,则必须确认专用 DNS 的路由和访问权限。通过分层测试、配置校验和容器重建验证,可以避免反复试错,也能减少 DNS 调整对现有业务的影响。✅