我正在尝试从主域的某些子文件夹中提供我的Web应用程序(基于Django / wsgi)。 我将docker用于我的应用程序和静态文件,因此我在服务器上使用了主要的nginx作为反向代理,在“ nginx”容器中使用了另一个nginx,用于将我的应用程序和uWSGI的内容路由到第二个容器中,该容器用于提供实际的Django数据
并且我希望我的应用可以以myserver.com/mytool
的形式在外部使用,与此同时,我不想在应用中的任何位置对mytool
进行硬编码。通常SCRIPT_NAME
标头用于这种类型的东西,因此这是主机上的Nginx配置:
server {
listen 80; # Just for sake of simplicity, of course in production it's 443 with SSL
location /mytool/ {
proxy_pass http://127.0.0.1:8000/;
include proxy_params;
proxy_set_header SCRIPT_NAME /mytool; # <--- Here I define my header which backend should use
}
}
然后在我的docker-compose
中,我为nginx公开了8000:80,这是内部nginx配置:
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
}
}
通过这种配置,我希望我的Django应用接收到SCRIPT_NAME标头,但显然没有。
同时,如果我定义了自定义标头,例如proxy_set_header X-something something;
,则它会正确转发,并且可以从Django中看到它。
我应该如何传递SCRIPT_NAME
以避免在代码中使用路径硬编码?
答案 0 :(得分:0)
这里有两个问题。
首先,nginx将包含下划线的标头视为无效,因此SCRIPT_NAME
标头不被容器中的nginx接受,因为从nginx角度来看,它是无效的。幸运的是,nginx指令underscores_in_headers可以为您提供帮助。
只需将underscores_in_headers on;
添加到Docker内部的nginx 的server
部分(而不添加到主机)。
完成此操作后,还有另一个问题-nginx在其名称前面转发在标题HTTP
之前的标头。因此,现在从Django端您将看到HTTP_SCRIPT_NAME
而不是SCRIPT_NAME
。但是,再次幸运的是,可以再次在Docker内部的nginx中使用uwsgi_param SCRIPT_NAME $http_script_name;
行来轻松修复它。
因此,Docker内部的最终nginx配置应如下所示:
server {
underscores_in_headers on; # <---- (1)
listen 80;
location / {
include uwsgi_params;
uwsgi_pass web:3031;
uwsgi_param SCRIPT_NAME $http_script_name; # <--- (2)
}
}