在 Docker 容器中使用主机 DNS 解析

Red*_*ddy 5 network-manager dns docker systemd-resolved

我认为这是 SO Network 中广泛讨论的问题之一。大多数解决方案要么是过时的,要么是最新的 Ubuntu (21.04)/Systemd 更改的陈旧建议。

问题:Docker 容器不支持来自主机网络的 VPN 更改。

尝试的解决方案:

  1. Docker 守护进程支持自定义 dns 解析。
    {
        "dns": ["172.17.0.1", "8.8.8.8", "8.8.4.4"]
    }
Run Code Online (Sandbox Code Playgroud)

此解决方案不适用于 Systemd DNS 解析。

resolvectl status

Link 7 (docker0)
Current Scopes: none
     Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported

Link 92 (tun0)
    Current Scopes: DNS
         Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 1.1.1.1
       DNS Servers: 1.1.1.1
        DNS Domain: consul vpn.net
Run Code Online (Sandbox Code Playgroud)
  1. 安装并绑定它的dnsmasq来docker0 interface/etc/dnsmasq.conf
interface=docker0
listen-address=172.17.0.1
Run Code Online (Sandbox Code Playgroud)

如果我使用bind-dynamic,它会失败并且bind-dynamic and bind-interfaces不能一起使用。我不得不从bind-interfaces正在设置的地方挖掘

终于在这里找到了:

cat /etc/dnsmasq.d/libvirt-daemon
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
       ? File: /etc/dnsmasq.d/libvirt-daemon
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
   1   ? bind-dynamic
   2   ? except-interface=virbr0
Run Code Online (Sandbox Code Playgroud)

将第 1 行更改bind-interfacesbind-dynamic并没有在dnsmasq.conf.

这似乎在重新启动docker and dnsmasq服务后有效。但是重新启动系统后,这不再起作用。只有当我按以下顺序启动服务docker first (so that 172.17.0.1 comes available) and dnsmasq following that 或者我必须明确地重新启动 dnsmasq 服务才能正确绑定到 172.17.0.1 时,它才有效。

我没有禁用 Systemd DNS 解析器以避免将来与网络管理器和任何其他组件发生任何升级/集成问题。

请提出解决方案

  1. 避免每次重启后都重启 dnsmasq 服务
  2. 有没有优雅的解决方案,而不是搞乱 SystemD/dnsmasq/docker。只是跨所有服务/接口的一个 DNS 解析?

Art*_*ild 1

如果我正确理解你的问题,你可以为你运行的每个容器提供主机 DNS 信息。我不明白为什么这不适用于解析dnsmasq DNS 解析(尽管我使用 Unbound)。

您应该将以下内容添加到运行的每个容器中以提供必要的 DNS 信息。我假设您的 DNS 解析器在地址 172.17.0.1 上运行(如果我错了,请纠正我)。

使用 Docker CLI:(只是一个随机示例配置)

docker run -d \
  --name <container-name> \
  --dns 172.17.0.1 \
  --dns 172.17.0.2 \ # your secondary DNS server if you have one
  --dns 8.8.8.8 \
  --dns 8.8.4.4 \
  -p <port>:<port> \
  -v /path/to/data/<container>:/path/to/data \
  --restart always \
  <repo>/<container>:<branch>
Run Code Online (Sandbox Code Playgroud)

使用 Docker Compose:(相同的随机配置)

version: '3'

  services:

    <service-name>:
      image: <repo>/<container>:<branch>
      container_name: <container-name>
      dns:
        - 172.17.0.1
        - 172.17.0.2 # your secondary DNS server if you have one
        - 8.8.8.8
        - 8.8.4.4
      ports:
        - <port>:<port>
      volumes:
        - /path/to/data/<container>:/path/to/data
      restart: always
Run Code Online (Sandbox Code Playgroud)

我已经用几个容器完成了此操作,它们使用我的内部 DNS 解析 DNS(我的地址是 10.10.2.2 和 10.10.2.4 并使用 Unbound,但我不明白为什么它应该有任何不同)。

我认为这种方法至少有两个优点:

  • 您不需要自定义或配置超出您通常所做的操作的 DNS 解析器 - 它“只”需要侦听主机(可以是本地计算机或任何其他 DNS 主机 - 在本例中为 172.17.0.1,即 172.17) .0.2(如果您有中学)。
  • 您也不需要使用自己的 DNS 解决方案自定义容器,因为 DNS 信息作为容器初始化的参数提供(如果需要,您甚至可以让不同的容器使用不同的 DNS 解决方案)。

我能想到的1个“缺点”:

  • 您需要为启动的每个容器提供 DNS 信息 - 但如果您保存容器配置,则只需为每个容器执行一次,并且 DNS 配置在大多数情况下应该是相似的。

我相信这个答案符合您的标准:

  • 避免每次重启后都重新启动 dnsmasq 服务
  • 有没有优雅的解决方案而不是搞乱 SystemD/dnsmasq/docker。跨所有服务/接口的简单 DNS 解析?


Alp*_*lpy 0

我会尝试在 docker 中运行 dnsmasq 的解决方案,如下所示:

https://blog.csainty.com/2016/09/running-dnsmasq-in-docker.html

其中 dnsmasq 将读取添加到 /etc/dnsmasq 的所有 .conf 文件(需要重新启动容器才能加载更改)。