nginx配置文件:server、server_name和upstream的理解

2 nginx nginx-config

我有一个从 github 项目继承的 nginx.conf 配置文件,我希望有人能解释一下我在做什么:

upstream hello_django {
    server web:8000;
}

server {
    listen 80;
    server_name react-wagtail-api.accordbox.com;
    location / {
        proxy_pass http://hello_django;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
        client_max_body_size 20M;
    }
    location /static/ {
        alias /app/static/;
    }
    location /media/ {
        alias /app/media/;
    }
}

server {
    listen 80;
    server_name react-wagtail.accordbox.com;
    location / {
      root   /usr/share/nginx/html/build;
      index  index.html index.htm;
      try_files $uri $uri/ /index.html;
    }
}
Run Code Online (Sandbox Code Playgroud)

upstream hello_django {
        server web:8000;
    }
Run Code Online (Sandbox Code Playgroud)

web一个服务(其他地方有一个 docker-compose 容器名称,它是web......它是对此的引用吗?)?具体定义是什么upstream

server_name react-wagtail-api.accordbox.com;
Run Code Online (Sandbox Code Playgroud)

如果我不定义 aserver_name例如,如果我还没有域,会发生什么?server_name 是在浏览器地址栏中输入的域名吗?我可以将其定义为本地IP并让我的域名提供商进行重定向吗?我可以将其定义为服务器的互联网IP并让我的域名提供商进行重定向吗?

由于同一端口上有两台服务器,我可以定义例如server_name my_internet_ip/app1server_name my_internet_ip/app2在端口 80 上为两台服务器提供服务吗?

Iva*_*sky 5

web一个服务(其他地方有一个 docker-compose 容器名称,它是web......它是对此的引用吗?)

一般来说,web这里是上游域名(也可以通过IP地址或UNIX套接字路径指定)。web但是,当在 docker-compose 上下文中执行此操作时,在 nginx 启动时,它将使用 docker 内部域名解析系统解析为容器内部 IP。

具体定义是什么upstream

对于这个特定的配置,使用任何一个都没有区别

upstream hello_django {
    server web:8000;
}
server {
    ...
    proxy_pass http://hello_django;
Run Code Online (Sandbox Code Playgroud)

或者直接在指令中指定上游地址proxy_pass

server {
    ...
    proxy_pass http://web:8000;
Run Code Online (Sandbox Code Playgroud)

真正有用的upstream用例包括故障转移(示例)或负载平衡(示例)。阅读ngx_http_upstream_module文档以了解所有可用的功能。

如果我没有定义 aserver_name例如,如果我还没有域,会发生什么?

要理解这一部分,请确保阅读官方文档中的以下两章:

您可以server_name完全省略服务器块中的指令。对于到达 nginx 正在侦听的 TCP 端口的任何 HTTP 请求,如果有更合适的服务器块,则定义的server块之一(通常是配置中出现的第一个块,除非使用指令default_server参数显式指定listen)将充当默认服务器不会被发现。HTTPHost请求标头值用于选择最合适的服务器块,与指定的server_name服务器块进行比较,它将与您在浏览器地址栏输入的内容完全相同(假设输入的 IP 地址/域名实际上是指向 nginx 服务器)。这意味着为侦听相同 TCP 端口的不同服务器块指定相同的服务器名称是没有意义的 - 将始终选择第一个服务器来处理此类请求,并且 nginx 会抱怨

nginx: [warn] conflicting server name "..." on 0.0.0.0:80, ignored
Run Code Online (Sandbox Code Playgroud)

警告信息。出于开发目的,您可以将所需的域名添加到hosts系统文件中,将它们指向您的本地计算机,例如

127.0.0.1  react-wagtail.accordbox.com
127.0.0.1  react-wagtail-api.accordbox.com
Run Code Online (Sandbox Code Playgroud)

这样,您将能够从本地浏览器使用这些域,生成的 HTTP 请求将包含正确的Host标头,并将使用本地 nginx 服务器实例进行处理。

由于同一端口上有两台服务器,我可以定义例如server_name my_internet_ip/app1server_name my_internet_ip/app2在端口 80 上为两台服务器提供服务吗?

不,看来您不了解 HTTP 协议的内部原理。在低级别的 HTTP 请求将类似于

nginx: [warn] conflicting server name "..." on 0.0.0.0:80, ignored
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,主机名和请求 URL 路径是两个完全不同的东西。通常此类任务是使用多个位置块来解决的:

127.0.0.1  react-wagtail.accordbox.com
127.0.0.1  react-wagtail-api.accordbox.com
Run Code Online (Sandbox Code Playgroud)

然而,它需要底层网络应用程序的支持。两个可用选项是

原因应该很明显 - 对任何第一个或第二个应用程序资产的每个请求都应以/app1//app2/前缀开头,以便使用正确的位置块进行处理。

正如您所看到的,我在这里使用的是/app1/and/app2/后缀,而不是/app1and /app2。这是许多人犯的一个非常常见的错误,不理解这两者之间的区别。虽然这似乎微不足道,但事实上,这两者在浏览上下文/方面有很大不同,在第一种情况和/或/app1/第二种/app2/情况下。除非您代理某种 API 端点而不是整个 Web 应用程序,否则您可能需要第二个端点。为了更简单,locationnginx 提供了一个指令特殊行为:

如果位置由以斜杠字符结尾的前缀字符串定义,并且请求由proxy_passfastcgi_passuwsgi_passscgi_passmemcached_pass或之一处理grpc_pass,则执行特殊处理。为了响应 URI 等于此字符串但没有尾部斜杠的请求,将返回带有代码 301 的永久重定向到所请求的 URI,并附加斜杠。如果不需要这样做,可以像这样定义 URI 和位置的精确匹配:

location /user/ {
    proxy_pass http://user.example.com;
}

location = /user {
    proxy_pass http://login.example.com;
}
Run Code Online (Sandbox Code Playgroud)

尽管我们可以使用 HTML 标记覆盖浏览上下文<base href="...">,但我强烈建议不要使用此解决方法,而应为代理 Web 应用程序使用正确的 URI 前缀。

  • 使用容器名称是一种常见的做法,它在任何地方都适用,而且我不认为容器IP是静态的东西或者可以在容器启动之前确定。是什么让你确定 nginx 无法将你的容器名称解析为 IP 地址?您最好将其作为一个单独的问题发布,包括 nginx 配置和 `docker-compose.yml` 文件。 (2认同)