同一虚拟机上单Nginx实例托管两个Gunicorn Flask服务返回404求助
问题核心排查解决思路
1. 优先排查Nginx proxy_pass路径改写规则
这是该场景下最高发的配置错误,proxy_pass末尾的斜杠会直接影响转发给Gunicorn的路径:
- 若配置为
location /myproject { proxy_pass http://unix:/tmp/myproject.sock; }:请求路径会完整传递给上游,Flask 收到的路径为/myproject/xxx,需要你的Flask路由前缀完全匹配该路径 - 若配置为
location /myproject { proxy_pass http://unix:/tmp/myproject.sock/; }:Nginx会自动去掉匹配到的/myproject前缀再转发,Flask收到的路径为/xxx,适合路由无前缀的Flask应用
你需要根据自己Flask应用的实际路由写法,严格对应proxy_pass的斜杠规则。
2. 配置Gunicorn SCRIPT_NAME 环境变量(推荐方案)
如果你的Flask应用本身路由无前缀(比如根路由写的是@app.route('/')),但需要对外暴露在/myproject子路径下,不需要改业务代码,直接在systemd配置中注入环境变量即可:
- 打开对应服务的systemd配置文件,在
[Service]段添加如下配置:# 第一个服务添加 Environment="SCRIPT_NAME=/myproject" # 第二个服务对应改为 /yourproject - 修改后重载配置重启服务:
systemctl daemon-reload systemctl restart myproject yourproject
该方案是子路径部署的标准实现,不需要调整Nginx路径改写规则。
3. 修正Nginx location匹配优先级
多location场景下容易出现匹配优先级错乱,建议给两个服务的location添加^~前缀,保证前缀匹配优先级高于正则匹配,参考配置如下:
server { listen 80; server_name 你的服务器IP或域名; location ^~ /myproject { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 根据你的路由规则决定是否加末尾斜杠 proxy_pass http://unix:/run/myproject.sock; } location ^~ /yourproject { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://unix:/run/yourproject.sock; } }
修改后验证配置合法性再重载Nginx:
nginx -t systemctl reload nginx
4. 验证Unix套接字权限
确认两个套接字文件的权限允许Nginx进程访问:
- 套接字文件权限建议设为
775,所属组要和Nginx运行用户(通常是www-data或nginx)一致 - 可以直接在Gunicorn启动参数中添加
--umask 0002保证生成的套接字权限符合要求
5. 快速定位路径传递问题
可临时在Flask应用中添加全局钩子打印实际收到的请求路径,快速区分是Nginx转发错误还是Flask路由错误:
from flask import request @app.before_request def log_received_path(): print(f"Actual path received: {request.path}")
通过Gunicorn运行日志即可确认转发的路径是否符合预期。
内容的提问来源于stack exchange,提问作者user2037606
相关产品推荐
相关产品推荐

