You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker Compose部署Flask+Gunicorn+Nginx时非根路由404问题排查

Nginx反向代理Flask应用非根路由404问题解决

问题概述

通过Docker Compose部署的Flask应用(Gunicorn运行),经Nginx反向代理后,根路由/可正常访问,但/dataset_detail/1等动态路由返回404错误。Nginx日志显示,系统尝试从本地静态文件目录/usr/share/nginx/html加载这些路由,而非转发至Flask应用。

错误日志

nginx-1  | 172.25.0.1 - - [22/May/2024:15:57:42 +0000] "GET / HTTP/1.1" 200 5086 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0"

nginx-1  | 2024/05/22 15:57:49 [error] 30#30: *1 open() "/usr/share/nginx/html/dataset_detail/1" failed (2: No such file or directory), client: 172.25.0.1, server: localhost, request: "GET /dataset_detail/1?page=1 HTTP/1.1", host: "0.0.0.0", referrer: "http://0.0.0.0/"

nginx-1  | 172.25.0.1 - - [22/May/2024:15:57:49 +0000] "GET /dataset_detail/1?page=1 HTTP/1.1" 404 153 "http://0.0.0.0/" "Mozilla/5.0 (X11; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0"

当前Nginx配置

events {
    worker_connections 1024;
    multi_accept on;
}
http {
    server {
        listen 80;
        server_name localhost;
        # Serve static files directly if possible
        location /static {
            alias /usr/share/nginx/html/static;
        }
        # Additional static file directories
        location /docs {
            alias /usr/share/nginx/html/docs;
            index index.html;
        }
        location /dataset {
            alias /usr/share/nginx/html/dataset;
            autoindex on;
        }
        # Handle Flask app routes
        location / {
            try_files $uri $uri/ @flask;
        }
        location @flask {
            proxy_pass http://app:5000;
            proxy_redirect off;
            proxy_set_header Host $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_request_body on;
        }
    }
}

问题原因

  1. 静态目录Location的前缀匹配冲突:Nginx的普通前缀匹配会优先选择最长的匹配路径。location /dataset作为前缀匹配规则,会捕获所有以/dataset开头的请求(包括/dataset_detail/1),并尝试通过alias从本地文件系统读取对应路径,而这些动态路由的文件显然不存在,因此返回404。
  2. 动态路由未进入转发逻辑:由于上述匹配冲突,/dataset_detail/1这类请求根本没有到达处理Flask转发的location /块,自然不会被转发至后端应用。

解决方案

修改静态目录的Location规则,使用^~修饰符限定精确前缀匹配,避免误捕获动态路由;同时确保动态路由能进入转发逻辑:

修改后的Nginx配置

events {
    worker_connections 1024;
    multi_accept on;
}
http {
    server {
        listen 80;
        server_name localhost;
        # 使用^~限定静态目录的精确前缀匹配,避免误匹配动态路由
        location ^~ /static/ {
            alias /usr/share/nginx/html/static/;
        }
        location ^~ /docs/ {
            alias /usr/share/nginx/html/docs/;
            index index.html;
        }
        location ^~ /dataset/ {
            alias /usr/share/nginx/html/dataset/;
            autoindex on;
        }
        # 处理所有动态路由请求
        location / {
            try_files $uri $uri/ @flask;
        }
        location @flask {
            proxy_pass http://app:5000;
            proxy_redirect off;
            proxy_set_header Host $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_request_body on;
        }
    }
}

关键修改说明

  • ^~修饰符:添加后,Nginx会优先匹配该规则,且仅当请求路径完全以指定前缀(如/dataset/)开头时才会触发静态文件处理,避免/dataset_detail这类路径被误匹配。
  • 路径末尾添加斜杠:静态目录的Location和Alias路径都添加末尾斜杠,确保路径拼接时不会出现错误(如避免/datasetdetail这类错误路径)。
  • 动态路由转发逻辑:所有未匹配静态目录的请求会进入location /,通过try_files尝试本地文件后,自动转发至@flask后端服务。

验证方法

  1. 重启Nginx容器:docker-compose restart nginx
  2. 访问动态路由(如/dataset_detail/1),确认返回正常响应而非404。

内容的提问来源于stack exchange,提问作者AayushPokharel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:04:56