当主机使用dnsmasq并且Google的DNS服务器受到防火墙保护时,DNS无法在docker容器中工作吗? [英] DNS not working within docker containers when host uses dnsmasq and Google's DNS server are firewalled?

查看:163
本文介绍了当主机使用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

(泊坞窗映像 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仅侦听来自本地主机的请求,并阻止来自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.

在Docker容器内DNS损坏的原因可能有多种.这个问题(和答案)涵盖了以下情况:

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天全站免登陆