【发布时间】:2018-10-04 12:05:13
【问题描述】:
症状是:宿主机有正常的网络访问权限,但容器内运行的程序无法解析 DNS 名称(在进一步调查之前可能看起来是“无法访问网络”)。
$ sudo docker run -ti mmoy/ubuntu-netutils /bin/bash
root@082bd4ead733:/# ping www.example.com
... nothing happens (timeout) ... ^C
root@082bd4ead733:/# host www.example.com
... nothing happens (timeout) ... ^C
(docker镜像mmoy/ubuntu-netutils是一个基于Ubuntu的简单镜像,包含ping和host,这里很方便,因为网络坏了我们不能apt install这些工具)
问题在于 docker 自动将 Google 的公共 DNS 配置为容器内的 DNS 服务器:
root@082bd4ead733:/# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 8.8.8.8
nameserver 8.8.4.4
这仅适用于许多配置,但当主机运行在 Google 的公共 DNS 被某些防火墙规则过滤的网络上时显然不起作用。
发生这种情况的原因是:
- Docker 首先尝试在主机和容器内配置相同的 DNS 服务器。
- 主机运行dnsmasq,一个DNS缓存服务。 dnsmasq 充当 DNS 请求的代理,因此主机
/etc/resolve.conf中的明显 DNS 服务器是nameserver 127.0.1.1,即 localhost。 - 主机的 dnsmasq 仅侦听来自 localhost 的请求并阻止来自 docker 容器的请求。
- 由于在 docker 中使用
127.0.1.1不起作用,docker 退回到 Google 的公共 DNS,这也不起作用。
DNS 在 docker 容器中损坏可能有多种原因。这个问题(和答案)涵盖了以下情况:
- 使用了 dnsmasq。要检查是否是这种情况:
- 在主机上运行
ps -e | grep dnsmasq。如果输出为空,则说明您没有运行 dnsmasq。 - 检查主机的resolv.conf,它可能包含类似
nameserver 127.0.1.1的条目。如果它包含nameserver 127.0.0.53,您可能正在运行systemd-resolved而不是dnsmasq。如果是这样,您将无法使用将 DNS 请求转发到 dnsmasq 的解决方案(使用listen-address=172.17.0.1的解决方案)。 systemd-resolved hardcodes the fact that it listens only on the 'lo' interface hence there's no easy way to adapt this solution。以下其他答案将适用于 systemd-resolved。
- 在主机上运行
- Google 的公共 DNS 已被过滤。运行
host www.example.com 8.8.8.8。如果它失败或超时,那么您就处于这种情况。
在此配置中获得正确 DNS 配置的解决方案是什么?
【问题讨论】:
标签: docker dns localhost dnsmasq