根本原因是nginx未正确配置静态资源路径:需用alias精确映射url前缀到物理目录,确保static_url_path与location一致,并检查权限及selinux限制。

Flask开发时静态资源正常,Nginx部署后返回404
根本原因不是Flask没找到文件,而是Nginx根本没把 /static/ 这类请求转发给Flask,而是自己尝试去磁盘找——但路径配错了。Flask的 url_for('static', filename='...') 生成的路径没问题,问题出在Nginx没按预期拦截并服务这些请求。
- 检查Nginx配置里是否包含针对
/static/的location块,且该块内有alias或root - 确认Flask项目中
static_folder实际路径(比如是./static还是./app/static),Nginx的alias必须精确对应其**物理目录** - 用
curl -I http://yoursite/static/css/main.css看响应头中的Server和Status,确认是Nginx返回的404(而非uWSGI/Gunicorn透传的404)
Nginx中用 alias 还是 root 配静态路径
选 alias。因为Flask的 /static/ 是URL前缀,你希望Nginx把 /static/js/app.js 映射到磁盘上 /var/www/myapp/static/js/app.js,而不是拼接成 /var/www/myapp/static/static/js/app.js——后者是 root 的行为。
-
location /static/ { alias /var/www/myapp/static/; }→ 正确:URL中/static/被完全替换为磁盘路径 -
location /static/ { root /var/www/myapp; }→ 错误:会去找/var/www/myapp/static/static/... -
alias值末尾必须带斜杠,且与location路径结尾一致(都带/),否则403或404
Flask的 static_url_path 和Nginx配置要对齐
如果你在创建Flask实例时改了静态URL前缀,比如 Flask(__name__, static_url_path='/assets'),那Nginx就不能再配 /static/,否则前端请求的是 /assets/main.css,Nginx却只拦截 /static/,自然跳过直接转给后端,而后端又不处理静态文件,最终404。
- 检查Flask初始化代码中是否设置了
static_url_path;若设为'/assets',Nginx必须配location /assets/ { alias /var/www/myapp/static/; } - 不建议随意改
static_url_path,除非有CDN或路径重写需求;保持默认/static最省事 - 模板中用
{{ url_for('static', filename='css/style.css') }}是安全的,它自动适配static_url_path,但Nginx必须同步响应这个URL路径
权限和SELinux可能让Nginx读不到文件
即使路径全对,Nginx worker进程用户(通常是 www-data 或 nginx)没有读取静态目录的权限,或者SELinux策略阻止访问,也会静默返回404(不是403)。
- 运行
ls -ld /var/www/myapp/static,确保目录对Nginx用户可读可执行(rx),文件至少可读(r) - 临时禁用SELinux测试:
sudo setenforce 0;若此时静态资源加载成功,说明需加策略,如sudo setsebool -P httpd_read_user_content 1 - 别忽略Nginx错误日志:
tail -f /var/log/nginx/error.log,里面常有Permission denied或directory index of "/var/www/myapp/static/" is forbidden这类关键线索
alias 少了个斜杠、Flask改了 static_url_path 却忘了同步Nginx、或者权限日志藏在角落没看。先盯死这三处,比反复重启服务更有效。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











