如果在上游找不到主机,则安装nginx不会崩溃

如果在上游找不到主机,则安装nginx不会崩溃,nginx,url-rewriting,proxypass,Nginx,Url Rewriting,Proxypass,我们在Docker的公共域下有几个rails应用程序,我们使用nginx将请求定向到特定的应用程序 our_dev_server.com/foo # proxies to foo app our_dev_server.com/bar # proxies to bar 配置如下所示: upstream foo { server foo:3000; } upstream bar { server bar:3000; } # and about 10 more... server {

我们在Docker的公共域下有几个rails应用程序,我们使用nginx将请求定向到特定的应用程序

our_dev_server.com/foo # proxies to foo app
our_dev_server.com/bar # proxies to bar
配置如下所示:

upstream foo {
  server foo:3000;
}

upstream bar {
  server bar:3000;
}

# and about 10 more...

server {
  listen *:80 default_server;

  server_name our_dev_server.com;

  location /foo {
      # this is specific to asset management in rails dev
      rewrite ^/foo/assets(/.*)$ /assets/$1 break;
      rewrite ^/foo(/.*)$ /foo/$1 break;
      proxy_pass http://foo;
  }

  location /bar {
      rewrite ^/bar/assets(/.*)$ /assets/$1 break;
      rewrite ^/bar(/.*)$ /bar/$1 break;
      proxy_pass http://bar;
  }

  # and about 10 more...
}
如果其中一个应用程序未启动,则nginx将失败并停止:

host not found in upstream "bar:3000" in /etc/nginx/conf.d/nginx.conf:6
我们不需要它们全部启动,但nginx在其他方面会失败。 如何使nginx忽略失败的上游

  • 如果您可以使用静态IP,那么只需使用它,它将启动并在没有响应时返回
    503

  • 使用
    resolver
    指令指向可以解析主机的内容,无论主机当前是否处于运行状态

  • 如果无法执行上述操作,请在
    位置
    级别解决此问题(这将允许Nginx启动/运行):


  • 使用
    上游
    的主要优点是定义一组服务器,这些服务器可以侦听不同的端口,并在它们之间配置负载平衡和故障切换

    在您的情况下,每个上游只定义一个主服务器,因此它必须启动

    相反,请为您的
    代理过程使用变量,并记住处理目标服务器关闭时可能出现的错误(404s、503s)。

    您不能使用
    --link
    选项,而是可以使用端口映射并将nginx绑定到主机地址

    示例:使用
    -p 180:80
    选项运行第一个docker容器,使用
    -p 280:80
    选项运行第二个容器

    运行nginx并为代理设置以下地址:

    proxy_pass http://192.168.1.20:180/; # first container
    proxy_pass http://192.168.1.20:280/; # second container
    

    对我来说,@Justin/@dashwuff答案的选项3解决了问题,但我必须将解析器IP更改为127.0.0.11(Docker的DNS服务器):

    但正如@Justin/@dashwuff所提到的,您可以使用任何其他外部DNS服务器。

    我遇到了相同的“找不到主机”问题,因为我的主机的一部分是使用
    $uri
    而不是
    $request\u uri
    进行映射的:

    proxy_pass http://one-api-service.$kubernetes:8091/auth;
    
    当请求更改为auth子请求时,
    $uri
    将丢失其初始值。将映射更改为使用
    $request\u uri
    而不是
    $uri
    解决了我的问题:

    map $request_uri $kubernetes {
        # ...
    }
    

    另一个简单快捷的解决方案是,我可以在主服务器没有爆炸的情况下启动和停止

        extra_hosts:
          - "dockerhost:172.20.0.1" # <-- static ipv4 gateway of the network ip here thats the only sorta downside but it works for me, you can ifconfig inside a container with the network to find yours, kinda a noob answer but it helped me
        networks:
          - my_network
    

    您是将应用程序容器与Nginx容器链接,还是将它们彼此分开运行?如果
    上游
    块中的主机在运行时未解析,则Nginx将以上述错误退出…如果您可以使用IP,则它将正常启动。在你的情况下使用
    resolver
    ()有效吗?@Justin我们每个应用都在单独的容器中,nginx也是如此。将它们与docker@Justin启动顺序很好,nginx在其他应用程序之后启动。我们只想运行其中的一些:)我有一个类似的设置(Nginx容器和appcontainer)。我们创建了一个Nginx映像,其中包含一个
    proxy.sh
    脚本,该脚本读取环境变量,并为每个变量动态添加
    上游
    条目,然后启动Nginx。这非常有效,因为当我们运行代理容器时,可以在运行时传入所需的上游。您可以做一些类似的事情,在启动时启用/禁用某些上游(或者像我的设置一样,只是在运行时添加所需的上游)。您的选项3对我来说非常有用。如果我没有指定解析程序,您知道nginx将缓存它解析的IP多长时间吗?谢谢!仅仅使用一个变量似乎会让nginx对itI不那么精明。我发现一个regex捕获组允许我跳过这个变量:
    location~ ^/foo/(.*)${proxy\u passhttp://foo/$1;}
    这对于TCP代理是如何工作的?似乎没有办法尝试tcp代理的选项3。@Charlie nginx中的此类错误几乎总是与缺少“;”在行尾签名:)>有关。相反,请为代理过程使用变量,并记住处理目标服务器停机时可能出现的错误(404、503)。你能详细说明一下怎么做吗?如果我执行
    设置$variablehttp://foo
    proxy\u pass$variable
    并保持foo“上游”(保持您提到的优势),然后我仍然在讨论OP提到的问题。正如您在其他示例中所看到的,它将是
    set$variable foo
    proxy\u pass http://$variable
    @danielgpm,如您所述,使用proxy_pass变量非常有效,解决了我的问题。如果你能更新你的答案,并举例说明这一点,那会对其他人有所帮助。如果我有不止一个答案,而我想忽略那些无法解决的答案,那该怎么办?你找到解决办法了吗?
    map $request_uri $kubernetes {
        # ...
    }
    
        extra_hosts:
          - "dockerhost:172.20.0.1" # <-- static ipv4 gateway of the network ip here thats the only sorta downside but it works for me, you can ifconfig inside a container with the network to find yours, kinda a noob answer but it helped me
        networks:
          - my_network
    
    server {
      listen 80;
      server_name servername;
    
      location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    
        proxy_pass https://dockerhost:12345;
    
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
      }
    }