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

Nginx try_files未加载index.html,请求转发至Flask的原因咨询

背景

我在AWS EC2实例上使用Nginx/Gunicorn/Flask搭建Web应用,整体运行正常,但存在一个疑问,希望得到解答或建议!

环境
  • AWS EC2实例
  • Python v3.10.10
  • Nginx v1.22.1
  • Gunicorn v21.2.0
  • Flask v2.3.2

已为Python创建名为“venv”的虚拟环境,路径为“/home/ec2-user/venv”

配置

Nginx配置文件(部分内容省略)@ /etc/nginx

user nginx;
worker_processes 1;
pid /run/nginx.pid;

events{
    worker_connections 1024;
}

http{
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    server{
        listen 80;
        server_name example.com;  <------ 虚拟域名!
        root /usr/share/nginx/html;
        location / {
            try_files $uri @flask;
        }
        location @flask {
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://localhost:8080;
        }
    }
}

执行以下步骤重启Nginx:

sudo systemctl stop nginx
sudo systemctl start nginx

在根目录“/usr/share/nginx/html”下存在index.html文件。

flask_app.py @ /home/ec2-user/python.source

from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
    return "Hello World"

if __name__ == '__main__':
    app.run()

wsgi.py @ /home/ec2-user/python.source

from flask_app import app

if __name__ == '__main__':
    app.run()

flask.service @ /etc/systemd/system

[Unit]
Description=Gunicorn instance to serve Flask
After=network.target
[Service]
User=ec2-user
Group=ec2-user
WorkingDirectory=/home/ec2-user/python.source
Environment="PATH=/home/ec2-user/venv/bin"
ExecStart=/home/ec2-user/venv/bin/gunicorn --bind 0.0.0.0:80 wsgi:app
[Install]
WantedBy=multi-user.target

执行以下步骤启动flask.service并设置开机自启:

sudo systemctl start flask
sudo systemctl enable flask
结果与疑问

当访问http://example.com/时,页面显示:

Hello World

我对try_files指令的理解是Nginx会从左到右尝试匹配资源,在此场景下,应该先匹配$uri,而根目录下存在index.html,但实际却显示Flask返回的Hello World,说明try_files未找到静态资源转而转发至Flask。请问该指令的匹配逻辑是怎样的?为何index.html未被加载?


解答

核心原因

问题出在try_files的匹配逻辑和缺少index指令的配合:

  1. 当访问http://example.com/时,$uri的值是/,这是一个目录路径,而非具体文件路径。
  2. try_files $uri @flask的逻辑是:仅尝试查找与$uri完全匹配的文件,不会自动去目录下查找index.html这类默认索引文件。
  3. 由于/不是一个存在的文件,Nginx直接触发最后一个选项@flask,将请求转发给Flask处理。

try_files的匹配逻辑

try_files的工作流程是:

  • 从左到右依次检查每个参数对应的文件/路径是否存在
  • 如果找到存在的文件,直接返回该文件
  • 如果所有文件都不存在,执行最后一个选项(可以是内部重定向、命名location或者返回错误码)

注意:try_files不会自动处理目录的默认索引文件,必须通过显式配置来支持。

解决方法

有两种方式可以让Nginx优先加载index.html:

方法1:修改try_files,添加目录匹配

将location /中的try_files指令修改为:

try_files $uri $uri/ @flask;

$uri/表示尝试访问$uri对应的目录,此时如果配置了index指令,Nginx会自动查找目录下的索引文件。

方法2:添加index指令

在server块或location /块中添加index指令,指定默认索引文件:

index index.html;

配合修改后的try_files(如上),当访问目录/时,Nginx会先尝试加载/usr/share/nginx/html/index.html,只有当该文件不存在时,才会转发给Flask。

额外注意点

你的flask.service中Gunicorn绑定的是0.0.0.0:80,但Nginx也监听80端口,这会导致端口冲突,理论上两个服务无法同时启动。而Nginx的proxy_pass指向的是localhost:8080,推测这里是配置笔误,建议将Gunicorn的绑定端口改为8080:

ExecStart=/home/ec2-user/venv/bin/gunicorn --bind 0.0.0.0:8080 wsgi:app

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:35:38