Nginx 在 Docker 中不会重新解析 DNS 名称

我正在运行 nginx 作为 docker-compose 模板的一部分。 在 nginx 配置中,我通过它们的 docker 主机名指向其他服务(例如 backendui)。 这很好工作,直到我尝试了这个技巧:

docker stop backend
docker stop ui
docker start ui
docker start backend

这使得后端和 UI 容器交换 IP 地址(docker 根据为每个新请求者提供下一个可用 IP 的 CIDR 来提供私有网络 IP)。这四个命令执行了一些罕见的情况,当时两个上游容器同时重新启动,但 nginx 容器没有。此外,我认为在基于 Kubernetes 的集群上运行 pod 时应该很常见。

现在,nginx 将 backend 主机解析为 UI 的 IP,ui 解析为后端的 IP。 重新加载 nginx 的配置可以解决问题(nginx -s reload)。 此外,如果我从 nginx 容器内部执行 nslookup,IP 始终正确解析。

因此,这将问题隔离为纯粹的 nginx 问题,围绕 DNS 缓存。

我尝试的事情:

  1. 我在 nginx 配置的 http {} 块下设置了解析器:
resolver 127.0.0.11 ipv6=off valid=10s;
  1. 互联网上提出的最常见的解决方案是在代理传递中使用变量(这有助于防止 nginx 在启动时解析和缓存 DNS 记录) - 根本没有任何区别:
server {
  <...>
  set $mybackend "backend:3000";
  location /backend/ {
    proxy_pass http://$mybackend;
  }
}
  1. 尝试在位置本身添加解析器行
  2. 尝试在 http{} 块级别上设置变量,使用 map:
http {
  map "" $mybackend {
    default backend:3000;
  }
  server {
   ...
  }
}
  1. 尝试使用 nginx 的 openresty 版本(https://hub.docker.com/r/openresty/openresty/)与 resolver local=true

这些解决方案都没有任何效果。只有在容器内部重新加载 nginx 配置或手动重新启动容器时,DNS 缓存才会被清除。

我目前的解决方法是使用在 docker-compose.yml 中声明的静态 docker 网络。但是这也有其缺点。

使用的 Nginx 版本:1.20.0(目前最新版) 使用的 Openresty 版本:1.13.6.1 和 1.19.3.1(目前最新版)

欢迎任何想法

2021-09-08 更新: 几个月后,我回到解决这个问题,仍然没有运气。看起来像是 nginx 中的错误 - 我不能让 nginx 重新解析 dns 名称。nginx 的 dns 缓存似乎没有超时,上面列出的任何选项都无法引入超时或触发 dns 刷新。

2022-01-11 更新: 我觉得问题确实出在 nginx 上。几个月前我以多种方式测试了我的配置,看起来我的 nginx.conf 中的其他东西阻止了 resolver 指令的 valid 参数正常工作。这是用于请求速率限制和缓存的 limit_req_zoneproxy_cache_path 指令,它们与 valid 参数不友好。我在 nginx 文档中找不到有关此信息的任何信息。 稍后我会重新确认我的假设。

点赞
用户13201147
用户13201147

也许是因为nginx用于上游服务器的DNS解析器仅在商业版nginx Plus中有效?

https://www.nginx.com/products/nginx/load-balancing/#service-discovery

2021-05-11 19:03:15
用户14570999
用户14570999

TLDR:你的互联网服务提供商可能会缓存 DNS 记录,而不考虑 TTL 值(例如 1 秒)。

我一直在试图在本地重新测试同样的事情。

  • 你的 Docker 可能正在使用本地解析器(127.0.0.11)。
  • 然后 DNS 可能会被你的操作系统缓存(你可以清除它,这是操作系统特定的)。
  • 接下来,你可能会在 WIFI/路由器上缓存它(没错!)
  • 然后它会到达你的 ISP,这已经超出了你的控制范围。

但是 nslookup 是你的朋友,你可以查询 nginx 和根 DNS 服务器之间的每个 DNS 服务器。

非常容易重现的一些内容(无需设置本地 DNS 服务器)

创建 TTL 为 1 秒的 Route 53 'A' 条目并尝试在你的托管区域中查询 AWS DNS 服务器(例如 ns-239.awsdns-29.com) 玩玩 dig / nslookup 命令

nslookup
set type=a
server ns-239.awsdns-29.com
your.domain.com

它会返回你设置的 IP

将 Route53 的 'A' 条目更改为其他 IP。

使用 dig / nslookup 确保你立即看到更改

然后在 nginx 中将解析器设置为 AWS 的 DNS 名称(仅用于测试)。 如果它有效,这意味着 DNS 在别处被缓存,这不再是 nginx 的问题!

在我的案例中,日出 WIFI 路由器在我重新启动它后才能看到新的 IP(我假设事情会在一些较长的时间后解决)。

当你的 nginx 编译使用

--with-debug

时,这是非常有用的,然后在 nginx 日志中,你可以看到给定的 DNS 是否已经解析以及 IP 是什么。

我的整个配置看起来像这样(这里是使用变量代理_pass 时必须设置的标准 Docker 解析器!)

        server {

                 listen 0.0.0.0:8888;
                 server_name nginx.my.custom.domain.in.aws;
                 resolver 127.0.0.11 valid=1s;

                 location / {
                     proxy_ssl_server_name on;
                     proxy_set_header X-Real-IP $remote_addr;
                     proxy_set_header X-Forwarded-Proto https;
                     proxy_set_header Host $host;
                     set $backend_servers my.custom.domain.in.aws;
                     proxy_pass https://$backend_servers$request_uri;
                 }
            }

然后你可以尝试用 curl -L http://nginx.my.custom.domain.in.aws --resolve nginx.my.custom.domain.in.aws 0.0.0.0:8888 来测试它。

2022-01-10 15:16:51
用户466227
用户466227

我原本也在同一件事情上(Docker Swarm)苦苦挣扎,实际上为了让它工作,我需要在我的配置中将 upstream 去掉。

这是一个良好运转的配置(在 NGINX 2.22 上测试过):

location ~* /api/parameters/(.*)$ {
    resolver 127.0.0.11 ipv6=off valid = 1s;
    set $bck_parameters parameters:8000;
    proxy_pass http://$bck_parameters/api/$1$is_args$args;
}

其中 $bck_parameters 不是一个 upstream,而是真正的服务器。 如果使用 upstream 做同样的事情,将会失败。

2022-11-04 21:20:13
用户16284652
用户16284652

经过长时间的搜索,我找到了一些关于uwsgi_pass的解决方案。同样的解决方案也适用于proxy_pass

    resolver 127.0.0.11 valid=10s;
    set $upstream_endpoint ${UWSGI_ADDR};
    location / {
        uwsgi_pass $upstream_endpoint;
        include uwsgi_params;
    }

其中UWSGI_ADDR是您的应用程序容器的名称和端口,例如app:8000

更新:

实际上,它来自于proxy_pass文档。

参数值可以包含变量。在这种情况下,如果地址是指定为域名,则在描述的服务器组中搜索该名称,并在找不到时使用解析器确定。

此外,您还可以在nginx开发人员撰写的博客“在变量中设置域名”节中找到有用的信息。博客链接

2023-02-22 09:43:48