修复 Container 无法访问外网 DNS 配置错误,最推荐的方法是修改 Docker 守护进程配置文件 daemon.json 指定公共 DNS,或在启动容器时使用 `--dns` 参数临时指定。注意重启 Docker 服务会导致所有容器短暂中断,生产环境需在维护窗口操作。
先说结论:Container DNS 故障通常源于宿主机 DNS 配置失效或 Docker 嵌入式 DNS 转发异常,优先检查宿主机解析能力再调整容器配置。
- 先确认:宿主机能否正常解析域名,检查 /etc/resolv.conf 是否指向无效地址
- 先处理:修改 /etc/docker/daemon.json 配置全局 DNS 或启动时添加 `--dns` 参数
- 再验证:在容器内执行 nslookup 或 ping 外网域名确认解析恢复
命令速用版
以下是直接修改配置和重启服务的常用命令,适用于大多数 Linux 环境下的 Docker 容器。
# 查看当前 Docker 配置
cat /etc/docker/daemon.json
# 临时启动容器指定 DNS
docker run `--dns` 8.8.8.8 `--dns` 1.1.1.1 -it ubuntu bash
# 修改配置后重启服务
systemctl restart docker为什么会这样
Container 默认继承宿主机的 DNS 设置,当宿主机 DNS 配置错误或 systemd-resolved 占用本地回环地址时,容器无法解析外网域名。Docker 守护进程会启动一个嵌入式 DNS 服务器监听 127.0.0.11,容器将该地址作为默认 DNS,若宿主机上游 DNS 不可达,嵌入式 DNS 也无法完成转发。
分步处理
按照以下顺序排查和修复,每一步操作后都建议检查状态,避免盲目重启服务。
步骤 1:检查宿主机 DNS 状态
在宿主机执行 nslookup 或 dig 命令,确认宿主机本身能解析外网域名。如果宿主机无法解析,优先修复宿主机网络配置,例如修改 /etc/resolv.conf 或检查 NetworkManager 设置。
步骤 2:检查 Docker daemon 配置
查看 /etc/docker/daemon.json 文件是否存在 dns 配置项。如果文件不存在,可以新建;如果存在,检查 dns 数组中的 IP 地址是否可达。推荐配置公共 DNS 如 8.8.8.8 或 223.5.5.5。
{
"dns": ["8.8.8.8", "1.1.1.1"]
}步骤 3:应用配置并重启
修改配置文件后,必须重启 Docker 服务才能生效。执行 systemctl restart docker 命令。注意该操作会重启所有运行中的容器,需评估业务影响。
步骤 4:单容器覆盖配置
如果不想重启服务,可以在运行特定容器时使用 `--dns` 参数覆盖全局配置。此方法仅对该容器生效,适合临时修复或测试。
怎么验证是否生效
修复完成后,进入容器内部进行网络测试,确保解析和连通性均正常。
验证命令:
# 进入容器
docker exec -it <容器 ID> bash
# 测试域名解析
nslookup www.google.com
# 测试网络连通性
ping -c 4 8.8.8.8
ping -c 4 www.google.com判断标准:nslookup 能返回非-authoritative answer 的 IP 地址,ping 域名无 unknown host 错误且能收到回复包。
常见坑
在处理 DNS 配置时,以下几个场景容易导致配置无效或反复故障。
- 127.0.0.53 问题:Ubuntu 等系统使用 systemd-resolved 时,/etc/resolv.conf 可能指向 127.0.0.53,容器无法访问宿主机的本地回环 DNS,需在 daemon.json 指定外部 DNS。
- 防火墙拦截:宿主机的 iptables 或 firewalld 可能拦截容器的 UDP 53 端口出站流量,检查 FORWARD 链规则。
- 网络插件冲突:使用 Calico、Flannel 等 CNI 插件时,部分插件会管理 DNS 配置,手动修改 daemon.json 可能被覆盖,需查阅插件文档。
- 配置语法错误:daemon.json 是严格的 JSON 格式,多一个逗号或缺少引号都会导致 Docker 服务启动失败,修改前建议备份。
常见问题
为什么容器内 DNS 服务器地址是 127.0.0.11?
这是 Docker 嵌入式 DNS 服务器的默认监听地址,用于容器间服务发现和外部域名转发,所有未指定 DNS 的容器默认都会使用该地址。
修改 daemon.json 后 Docker 启动失败怎么办?
通常是 JSON 格式错误,查看 journalctl -u docker 日志定位错误行,恢复备份的配置文件或修正语法后重试。
Kubernetes Pod DNS 失败怎么修复?
K8s 环境需检查 CoreDNS Pod 状态和 ConfigMap 配置,通常通过 kubectl edit configmap coredns -n kube-system 修改上游 DNS,而不是修改 Docker 配置。
参考来源
- Docker Official Documentation, Container networking - DNS services, https://docs.docker.com/config/containers/container-networking/#dns-services
- Ubuntu Documentation, systemd-resolved, https://ubuntu.com/server/docs/service-networking