docker - 当主机使用 dnsmasq 并且 Google 的 DNS 服务器有防火墙时,DNS 在 docker 容器中不起作用?

标签 docker dns localhost dnsmasq

症状是:宿主机有正常的网络访问权限,但是容器内运行的程序无法解析 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的简单镜像,包含pinghost,这里很方便,因为网络坏了我们不能apt install 这些工具)

问题在于 docker 自动将 Google 的公共(public) 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 的公共(public) 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 的公共(public) DNS,这也不起作用。

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

在此配置中获得正确 DNS 配置的解决方案是什么?

最佳答案

一个干净的解决方案是配置 docker+dnsmasq,以便将来自 docker 容器的 DNS 请求转发到主机上运行的 dnsmasq 守护进程。

为此,您需要 configure dnsmasq to listen to the network interface used by docker ,通过添加文件 /etc/NetworkManager/dnsmasq.d/docker-bridge.conf:

$ cat /etc/NetworkManager/dnsmasq.d/docker-bridge.conf
listen-address=172.17.0.1

然后重新启动网络管理器以考虑配置文件:

sudo service network-manager restart

完成后,您可以将 172.17.0.1(即 docker 中的主机 IP 地址)添加到 DNS 服务器列表中。这可以使用命令行来完成:

$ 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(不存在就创建):

$ cat /etc/docker/daemon.json                      
{
  "dns": [
    "172.17.0.1",
        "8.8.8.8",
        "8.8.4.4"
  ]
}

(如果 dnsmasq 失败,这将退回到 Google 的公共(public) DNS)

您需要重新启动 docker 以考虑配置文件:

sudo service docker restart

然后就可以照常使用docker了:

$ 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

关于docker - 当主机使用 dnsmasq 并且 Google 的 DNS 服务器有防火墙时,DNS 在 docker 容器中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49998099/

相关文章:

spring - docker 镜像正在运行,但无法访问 Spring Boot 应用程序中的其余端点

bash - 从脚本中分离 docker run 而不杀死容器

WordPress 本地主机 :3000 returns SSL_ERROR_RX_RECORD_TOO_LONG with MAMP 6

iis - 多个本地主机 :80-bound sites in IIS?

iis - 我如何映射 http ://localhost:8080 to http://mysites in iis7?

mysql - Xampp 连接到 MariaDB 而不是 mysql (KNP/SymfonyCasts 教程 "how to speak database")

amazon-web-services - 配置的日志驱动程序不支持读取 : Docker

php - 适用于 PHP 7 的 Docker gd 模块

cocoa-touch - Cocoa 的 CFHost 支持 IDN 吗?

php - CentOS 7,通过 apache 的 php 脚本不解析主机名。如果我直接使用 ip 它可以工作