当主机使用 dnsmasq 并且 Google 的 DNS 服务器有防火墙时,DNS 在 docker 容器中不起作用? [英] DNS not working within docker containers when host uses dnsmasq and Google's DNS server are firewalled?

查看:16
本文介绍了当主机使用 dnsmasq 并且 Google 的 DNS 服务器有防火墙时,DNS 在 docker 容器中不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现象是:宿主机可以正常访问网络,但是容器内运行的程序无法解析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

(docker 镜像 mmoy/ubuntu-netutils 是一个简单的镜像基于 Ubuntu,包括 pinghost,这里很方便,因为网络坏了,我们不能 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 仅侦听来自 localhost 的请求并阻止来自 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 is nameserver 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.

DNS 在 docker 容器中被破坏可能有多种原因.此问题(和答案)涵盖以下情况:

There may be several reasons why DNS is broken within docker containers. This question (and answers) covers the case where:

  • 使用了 dnsmasq.要检查是否是这种情况:
    • 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 contains nameserver 127.0.0.53, you're probably running systemd-resolved instead of dnsmasq. If so, you won't be able to use the solution forwading DNS requests to dnsmasq (the one using 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. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆