nginx 根据主机名中的索引反向代理到不同的应用程序

nginx reverse proxy to different applications based on an index in the host name

以前,我有一个可在 DNS staging.example.com/ 后面访问的暂存环境。这个地址后面是一个 nginx 代理,配置如下。请注意,我的代理要么重定向

server {
  listen 80;
  listen 443 ssl;
  server_name
      staging.example.com
  ;

  location / {
    try_files /maintenance.html @app1;
  }

  location ~ /(faq|about_us|terms|press|...) {
      try_files /maintenance.html @app2;
  }

  [...] # Lots of similar config than redirects either to app1 or app2

  # Application hosted on s3 + CloudFront
  location @app1 {
    proxy_set_header Host app1-staging.example.com;
    proxy_pass http://d2c72vkj8qy1kv.cloudfront.net;
  }

  # Application hosted behind a load balancer
  location @app2 {
    proxy_set_header Host app2-staging.example.internal;
    proxy_set_header X-ALB-Host $http_host;
    proxy_pass https://staging.example.internal;
  }
}

现在,我的团队需要更多的暂存环境。我们还没有准备好过渡到 docker 部署(最终目标是能够为我们需要测试的每个分支生成一个完整的基础设施……考虑到我们的团队规模,这有点过分了),我正在尝试取而代之的是一些技巧,这样我们就可以轻松地获得更多的暂存环境使用大致相同的 nginx 配置

假设我已经创建了一些带有 index_i 的 DNS 名称,例如 staging1.example.comstaging2.example.com。所以我的 nginx 代理将接收主机 header 看起来像 staging#{index_i}.example.com

的请求

我在想做什么:

我正在尝试拉出这样的东西

# incoming host : staging{index_i}.example.com`
server {
  listen 80;
  listen 443 ssl;
  server_name
      staging.example.com
      staging1.example.com 
      staging2.example.com # I can list them manually, but is it possible to have something like `staging*.example.com` ?
  ;
[...]
location @app1 {
    proxy_set_header Host app1-staging$index_i.example.com; # Note the extra index_i here
    proxy_pass http://d2c72vkj8qy1kv.cloudfront.net/$index_i; # Here proxy_passing to a subfolder named index_i
  }

  location @app2 {
    proxy_set_header Host app2-staging$index_i.example.internal; # Note the extra index_i here
    proxy_set_header X-ALB-Host $http_host;
    proxy_pass http://staging$index_i.example.internal; # Here I am just forwarding the host header basically
  }

所以最终我的问题是 - 当我的 nginx 服务器接收到连接时,我可以从请求主机 header 中提取 index_i 变量(可能使用一些正则表达式吗?) - 如果是,如何使用 index_i 有效地实现 app1 和 app2 块?

在查看了其他几个问题后,我得出了这个完美运行的配置:可以在主机名中使用正则表达式来提取所述变量。

不利的一面是,对于我的静态单页应用程序,要使其与 S3 一起使用,我必须为每个 "staging index" 创建一个存储桶(因为 S3 上的静态托管与网站托管/a单个 index.html 用于 404)。这反过来又使我无法在我的(以前是单一的)s3 之前使用单一的 Cloudfront 发行版。

这是在 ALB 后面使用带有 create-react-app 前端和服务器端呈现的代理的示例

server {
  listen 80;
  listen 443 ssl;
  server_name ~^staging(?<staging_index>\d*).myjobglasses.com$

  location @create-react-app-frontend {
      proxy_pass http://staging$staging_index.example.com.s3-website.eu-central-1.amazonaws.com;
  }

  location @server-side-rendering-app {
      # Now Amazon Application Load Balancer can redirect traffic based on ANY HTTP header
      proxy_set_header EXAMPLE-APP old-frontend;
      proxy_pass https://staging$staging_index.myjobglasses.com;
  }