当主机使用dnsmasq并且Google的DNS服务器受到防火墙保护时,DNS无法在docker容器中工作吗? [英] DNS not working within docker containers when host uses dnsmasq and Google's DNS server are firewalled?
问题描述
症状是:主机具有适当的网络访问权限,但是在容器中运行的程序无法解析DNS名称(在进行更多调查之前,它似乎是无法访问网络").
The symptom is: the host machine has proper network access, but programs running within containers can't resolve DNS names (which may appear to be "can't access the network" before investigating more).
$ 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
(泊坞窗映像 mmoy/ubuntu-netutils 是一个简单的映像基于Ubuntu,其中包含ping
和host
,在此非常方便,因为网络中断了,我们不能apt install
这些工具)
(The docker image mmoy/ubuntu-netutils is a simple image based on Ubuntu with ping
and host
included, convenient here since the network is broken and we can't apt install
these tools)
问题来自docker自动将Google的公共DNS配置为容器内的DNS服务器的事实:
The issue comes from the fact that docker automatically configured Google's public DNS as DNS server within the container:
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的网络上运行时,显然不起作用.
This just works in many configurations, but obviously doesn't when the host runs on a network where Google's public DNS are filtered by some firewall rules.
发生这种情况的原因是:
The reason this happened is:
- Docker首先尝试在主机上和容器内配置相同的DNS服务器.
- 主机运行 dnsmasq (一种DNS缓存服务). dnsmasq充当DNS请求的代理,因此主机
/etc/resolve.conf
中的明显DNS服务器是nameserver 127.0.1.1
,即localhost. - 主机的dnsmasq仅侦听来自本地主机的请求,并阻止来自docker容器的请求.
- 由于在docker中使用
127.0.1.1
无效,因此docker退回到了Google的公共DNS,这也无效.
- Docker first tries configuring the same DNS server(s) on the host and within the container.
- The host runs dnsmasq, a DNS caching service. dnsmasq acts as a proxy for DNS requests, hence the apparent DNS server in the host's
/etc/resolve.conf
isnameserver 127.0.1.1
, i.e. localhost. - The host's dnsmasq listens only for requests comming from localhost and blocks requests coming from the docker container.
- Since using
127.0.1.1
within docker doesn't work, docker falls back to Google's public DNS, which do not work either.
在Docker容器内DNS损坏的原因可能有多种.这个问题(和答案)涵盖了以下情况:
There may be several reasons why DNS is broken within docker containers. This question (and answers) covers the case where:
-
使用
- 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
的DNS请求). 系统解析的硬代码它仅在"lo"接口上监听的事实,因此没有简单的方法来适应此解决方案.以下其他答案将适用于systemd-resolved.
- dnsmasq is used. To check whether this is the case:
- Run
ps -e | grep dnsmasq
on the host. If the output is empty, you're not running dnsmasq. - Check the host's resolv.conf, it probably contains an entry like
nameserver 127.0.1.1
. If it containsnameserver 127.0.0.53
, you're probably runningsystemd-resolved
instead of dnsmasq. If so, you won't be able to use the solution forwading DNS requests to dnsmasq (the one usinglisten-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. Other answers below will work with systemd-resolved.
在此配置中获得正确的DNS配置的解决方案是什么?
What are the solutions to get a proper DNS configuration in this configuration?
推荐答案
一种干净的解决方案是配置docker + dnsmasq,以便将来自docker容器的DNS请求转发到主机上运行的dnsmasq守护程序.
A clean solution is to configure docker+dnsmasq so than DNS requests from the docker container are forwarded to the dnsmasq daemon running on the host.
为此,您需要配置dnsmasq来侦听由docker ,通过添加文件
/etc/NetworkManager/dnsmasq.d/docker-bridge.conf
:For that, you need to configure dnsmasq to listen to the network interface used by docker, by adding a file
/etc/NetworkManager/dnsmasq.d/docker-bridge.conf
:$ cat /etc/NetworkManager/dnsmasq.d/docker-bridge.conf listen-address=172.17.0.1
然后重新启动网络管理器以考虑配置文件:
Then restart network manager to have the configuration file taken into account:
sudo service network-manager restart
完成后,您可以将
172.17.0.1
(即来自docker内部的主机的IP地址)添加到DNS服务器列表中.可以使用命令行完成此操作:Once this is done, you can add
172.17.0.1
, i.e. the host's IP address from within docker, to the list of DNS servers. This can be done either using the command-line:$ sudo docker run -ti --dns 172.17.0.1 mmoy/ubuntu-netutils bash root@7805c7d153cc:/# ping www.example.com PING www.example.com (93.184.216.34) 56(84) bytes of data. 64 bytes from 93.184.216.34: icmp_seq=1 ttl=54 time=86.6 ms
...或通过docker的配置文件
/etc/docker/daemon.json
(如果不存在则创建它):... or through docker's configuration file
/etc/docker/daemon.json
(create it if it doesn't exist):$ cat /etc/docker/daemon.json { "dns": [ "172.17.0.1", "8.8.8.8", "8.8.4.4" ] }
(如果dnsmasq失败,它将退回到Google的公共DNS)
(this will fall back to Google's public DNS if dnsmasq fails)
您需要重新启动docker才能将配置文件考虑在内:
You need to restart docker to have the configuration file taken into account:
sudo service docker restart
然后您可以照常使用docker:
Then you can use docker as usual:
$ sudo docker run -ti mmoy/ubuntu-netutils bash root@344a983908cb:/# ping www.example.com PING www.example.com (93.184.216.34) 56(84) bytes of data. 64 bytes from 93.184.216.34: icmp_seq=1 ttl=54 time=86.3 ms
这篇关于当主机使用dnsmasq并且Google的DNS服务器受到防火墙保护时,DNS无法在docker容器中工作吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- Run
- 在主机上运行