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

Nginx不会在Docker中重新解析DNS名称,nginx,docker-compose,nginx-config,docker-networking,docker-network,Nginx,Docker Compose,Nginx Config,Docker Networking,Docker Network,我正在运行nginx作为docker compose模板的一部分。 在nginx配置中,我通过docker主机名引用其他服务(例如,后端,ui)。 这很好,直到我做了这个把戏: docker stop backend docker stop ui docker start ui docker start backend 这使得后端和ui容器可以交换IP地址(docker提供私有网络IP,其基础是将CIDR中的下一个可用IP提供给每个新请求者)。执行的这4个命令模拟了两个上游容器同时重新启动但n

我正在运行nginx作为docker compose模板的一部分。 在nginx配置中,我通过docker主机名引用其他服务(例如,
后端
ui
)。 这很好,直到我做了这个把戏:

docker stop backend
docker stop ui
docker start ui
docker start backend
这使得后端和ui容器可以交换IP地址(docker提供私有网络IP,其基础是将CIDR中的下一个可用IP提供给每个新请求者)。执行的这4个命令模拟了两个上游容器同时重新启动但nginx容器没有重新启动的罕见情况。此外,我认为,在基于Kubernetes的集群上运行POD时,这应该是一种非常常见的情况

现在,nginx将
后端
主机解析为ui的IP,将
ui
解析为后端的IP。 重新加载nginx的配置确实有帮助(
nginx-s reload
)。 另外,如果我在nginx容器中执行nslookup,那么IP总是正确解析的

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

我尝试过的事情:

  • 我在nginx config的http{}块下设置了解析器:
  • 互联网上的人们提出的最常见的解决方案是在代理传递中使用变量(这有助于防止nginx在启动时解析和缓存DNS记录)这根本没有任何区别:
  • 尝试将nginx()的openresty fork与
    resolver local=true
  • 所有的解决方案都没有产生任何效果。只有在容器内重新加载nginx配置或手动重新启动容器时,才会擦除DNS缓存

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

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


    如果您有任何想法,我将不胜感激。

    也许是因为nginx针对上游服务器的DNS解析器只在商业版nginx plus中工作


    您是否在nginxs github上提交了错误报告?在我看来像个bug。@工具我还没有提交bug,但我可能会提交。值得关注的是,将变量添加到proxy_过程似乎有助于其他人,因为这是其他人使用的常见(但未记录)解决方案。但这似乎对我根本不起作用。几年前,当我上次尝试它时,它对我也不起作用。所以我想知道我是否遗漏了什么,是不是解决方法。我昨天已经看过文件了。很明显,当像您这样给出
    有效的
    参数时,nginx应该忽略TTL并在该时间间隔重新检查。因此,最迟在10秒后nginx应该正确开始路由。>默认情况下,nginx使用响应的TTL值缓存答案。可选的有效参数允许覆盖它。另一个有趣的测试是等待10分钟,然后看看它是否有效。因为docker解析器发送的默认TTL是600秒。在此之后,nginx应该尊重TTL值,即使它不尊重
    有效的
    参数。你也可以试着降低TTL dockers解析器的使用。我需要回到这个问题上来,测试建议的参数。我目前正在与其他项目脱轨,但应该能够得到我的手上这个soonish。这是事实,但是互联网上的其他开发人员声称,使用变量将dns名称传递给proxy_pass会起到作用,因为这会迫使Nginx动态解析dns名称。我认为nginx团队改变了这种未记录的行为,但在过去的几年里,人们似乎一直在使用这种技巧,而这对我来说从来都不起作用。我认为只有在使用代理传递请求的情况下,代理传递解决方案才有效。如果您需要使用fastcgi,它将不起作用。我没有使用fastcgi。我所做的就是基本上改变了
    location/api/{proxy\u passhttp://backend:3000/;}
    进入
    位置/api/{;设置$var\u后端”http://backend:3000“proxy_pass http://$var_backend/;}
    (跳过此处正确处理URI的
    重写部分)
    
    resolver 127.0.0.11 ipv6=off valid=10s;
    
    server {
      <...>
      set $mybackend "backend:3000";
      location /backend/ {
        proxy_pass http://$mybackend;
      }
    }
    
    http {  
      map "" $mybackend {
        default backend:3000;
      }
      server {
       ...
      }
    }