问题:
我正在尝试通过 Nginx 提供 Flask 应用程序(与 Gunicorn 一起运行)。我的项目是使用容器设置的,并使用 Docker Compose 进行编排。我已编辑
nginx.conf
来服务我的应用程序。
我面临的问题是我可以访问 Flask 应用程序的
/
路径,但是当我尝试导航到应用程序中的任何其他链接时,我收到 404 Not Found
错误。
Nginx 日志
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.conf
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;
}
}
}
附加信息
/
工作正常并返回预期的页面。/dataset_detail/1
,会返回 404 Not Found
错误。/usr/share/nginx/html
目录提供这些路由,而不是将请求传递给 Flask 应用程序。问题:
什么可能导致 Nginx 正确服务根路由,但对其他路由返回 404 错误?如何配置 Nginx 将所有请求正确转发到 Flask 应用程序?
问题在于,默认情况下,nginx 位置块使用“前缀匹配”策略。
来自文档:
位置可以由前缀字符串或正则表达式定义。正则表达式使用前面的“~*”修饰符(对于不区分大小写的匹配)或“~”修饰符(对于区分大小写的匹配)来指定。为了找到与给定请求匹配的位置,nginx 首先检查使用前缀字符串(前缀位置)定义的位置。其中,选择并记住具有最长匹配前缀的位置。然后按照正则表达式在配置文件中出现的顺序进行检查。正则表达式的搜索在第一个匹配处终止,并使用相应的配置。如果未找到与正则表达式匹配的内容,则使用之前记住的前缀位置的配置。
因此,
location /dataset
将请求与 /dataset_detail/1
相匹配,查找静态文件并在未找到时返回 404。
我不确定适合您的特定应用程序的最佳解决方案是什么,但您可能可以使用
location
正则表达式匹配器来更准确地检测已知/良好的静态文件,或者可能使用 try_files
重定向到 @flask
如果找不到静态文件。