首页 > 解决方案 > 使用 nginx 为每个位置提供不同的静态文件夹

问题描述

TL;博士

我需要为托管在同一台机器上但位于两个非常不同的路径上的两个容器化应用程序(每个在不同的端口上)提供服务,并使用nginx反向代理使用它们自己的静态子文件夹。

语境

我经历了很多关于额外复杂内容的 Q/A,这对我理解如何使用nginx为每个位置提供一些静态文件夹的本质没有太大帮助。

让我用一个简单而整洁的起始反向代理配置来解释“每个位置”的含义:

server {
    listen 80;
    listen [::]:80;

    root /var/www;
    server_name my.server.org;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /app-a {
        proxy_pass http://127.0.0.1:8080/;
    }

    location /app-b {
        proxy_pass http://127.0.0.1:8081/;
    }
}

这很好用,只是不提供静态文件(css、js、...)。

因此,我将其更改如下以检索这些文件app-b

server {
    listen 80;
    listen [::]:80;

    root /var/www;
    server_name my.server.org;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /app-a {
        proxy_pass http://127.0.0.1:8080/;
    }

    location /app-b {
        proxy_pass http://127.0.0.1:8081/;
    }
    location ^~ /static/ {
        include /etc/nginx/mime.types;
        root /home/debian/projects/crystallography/web/app-b/;
    }
}

而且效果更好;我现在有这些静态文件用于app-b. 但当然还是什么都没有app-a

现在,您明白我的意思了……我还需要提供app-a自己的静态文件夹。


我测试过的

这是我尝试过的两个主要想法(并且不起作用)+其他变体(也不起作用):

  1. 添加一个额外的静态位置(似乎先验是一种干净的方式)
server {
    listen 80;
    listen [::]:80;

    root /var/www;
    server_name my.server.org;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /app-a {
        proxy_pass http://127.0.0.1:8080/;
    }
    location ^~ /static/ {
        include /etc/nginx/mime.types;
        root /media/biology/swamps/frog-migration/app-a/; # this is a totally different path than app-b
    }

    location /app-b {
        proxy_pass http://127.0.0.1:8081/;
    }
    location ^~ /static/ {
        include /etc/nginx/mime.types;
        root /home/debian/projects/crystallography/web/app-b/;
    }
}

这显然与来自的静态文件夹冲突app-b,所以nginx -t自然会失败:

nginx: [emerg] duplicate location "/static/" in /etc/nginx/sites-enabled/proxy-pass.conf:24
nginx: configuration file /etc/nginx/nginx.conf test failed
  1. 服务器定义的重复(这对我来说听起来不是一个好主意):
server {
    listen 80;
    listen [::]:80;

    root /var/www;
    server_name my.server.org;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /app-a {
        proxy_pass http://127.0.0.1:8080/;
    }
    location ^~ /static/ {
        include /etc/nginx/mime.types;
        root /media/biology/swamps/frog-migration/app-a/;
    }
}

server {
    listen 80;
    listen [::]:80;

    root /var/www;
    server_name my.server.org;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /app-b {
        proxy_pass http://127.0.0.1:8081/;
    }
    location ^~ /static/ {
        include /etc/nginx/mime.types;
        root /home/debian/projects/crystallography/web/app-b/;
    }
}

语法没问题,但我有一些警告nginx -t

nginx: [warn] conflicting server name "my.server.org" on 0.0.0.0:80, ignored
nginx: [warn] conflicting server name "my.server.org" on [::]:80, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

但最重要的app-b是,不再可访问(返回 404)。

问题

使用nginx,我怎样才能让两个(当然更多)不同的应用程序(位于同一主机上的两个不同路径)彼此相邻,在它们自己的气泡中并使用它们自己的静态子文件夹提供服务(即两个应用程序的静态文件之间没有干扰)?

标签: nginx-reverse-proxystatic-files

解决方案


我终于找到了这个解决方案,其中一台服务器正在运行,但我不是 100% 满意,因为我想避免该alias指令,因为路径遍历漏洞

免责声明:所以请不要忘记别名位置中的斜杠。

server {
    listen 80;
    listen [::]:80;

    #root /var/www;
    server_name server.domain.org;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /app-a {
        proxy_pass http://127.0.0.1:8080/;
        location /app-a/static/ {
            include /etc/nginx/mime.types;
            alias /media/biology/swamps/frog-migration/app-a/static/;
        }
    }

    location /app-b {
        proxy_pass http://127.0.0.1:8081/;
        location /app-b/static/ {
            include /etc/nginx/mime.types;
            alias /home/debian/projects/crystallography/web/app-b/static/;
        }
    }

}

特别是,它不适用于root指令;因为它发送的页面没有任何静态文件(这些静态文件上的错误 404,我不明白为什么):

server {
    listen 80;
    listen [::]:80;

    #root /var/www;
    server_name server.domain.org;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /app-a {
        proxy_pass http://127.0.0.1:8080/;
        location /app-a/static/ {
            include /etc/nginx/mime.types;
            root /media/biology/swamps/frog-migration/app-a/;
        }
    }

    location /app-b {
        proxy_pass http://127.0.0.1:8081/;
        location /app-b/static/ {
            include /etc/nginx/mime.types;
            root /home/debian/projects/crystallography/web/app-b/;
        }
    }

}

除了上面的工作解决方案之外,我还必须将我的 Flask 应用程序中的静态路径更改为:
/app-a/static而不是仅/static适用于 app-a
/app-b/static而不仅仅是/static适用于 app-b。

但是通过这样做,您肯定希望将您的app-aapp-b字符串放在环境变量中的某个位置,而不是对它们进行硬编码。


推荐阅读