Nginx+uWSGI架构下uWSGI托管静态文件DEBUG=False时404排查
采用Nginx+uWSGI架构,指定由uWSGI托管静态文件,未在Nginx中配置静态文件规则。相关配置如下:
Nginx配置
server { listen 80; server_name dockerhost; charset utf-8; location / { proxy_pass http://127.0.0.1:8011/; include /etc/nginx/uwsgi_params; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_pass_header X-XSRF-TOKEN; } }
uWSGI启动命令
uwsgi --http :8011 --processes 4 --threads 1 --module myapp.wsgi --logto /tmp/mylog.log
Django配置
settings.py
STATIC_URL = '/static/' STATIC_ROOT = "/usr/src/app/static" STATICFILES_DIRS = ( os.path.join(BASE_DIR,'frontend/dist'), )
urls.py
urlpatterns += [ path('sp/', SeparateView.as_view()) ] if settings.DEBUG: urlpatterns += [ re_path(r'^static/(?P<path>.*)$', views.serve), ]
问题现象:DEBUG=True时静态文件正常加载;DEBUG=False时,模板中{% static %}标签生成的路径返回404,已执行manage.py collectstatic且确认/usr/src/app/static目录存在文件。
补全生产环境静态文件路由:DEBUG=False时,urls.py中仅在DEBUG模式下添加的
static路由会被移除,Django默认不会在生产环境处理静态文件请求。有两种处理方式:- 直接在urls.py中添加生产环境可用的静态路由(注意:Django官方不推荐此生产方案,但适配uWSGI托管场景可使用):
from django.conf.urls.static import static from django.conf import settings urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) - 配置uWSGI直接映射静态文件,无需Django处理,修改uWSGI启动命令,添加静态映射参数:
uwsgi --http :8011 --processes 4 --threads 1 --module myapp.wsgi --logto /tmp/mylog.log --static-map /static/=/usr/src/app/static/
- 直接在urls.py中添加生产环境可用的静态路由(注意:Django官方不推荐此生产方案,但适配uWSGI托管场景可使用):
验证uWSGI静态映射有效性:若用了
--static-map参数,需确认路径拼写正确,同时检查uWSGI进程是否有/usr/src/app/static目录的读取权限。可直接访问http://dockerhost/static/[目标文件名]测试,同时查看/tmp/mylog.log日志,确认是否有静态文件请求的处理记录。排查Nginx是否拦截请求:虽然未配置静态文件规则,但需确认Nginx的
location /是否完整转发所有请求到uWSGI,无隐式的静态文件处理规则。可查看Nginx错误日志(通常路径为/var/log/nginx/error.log),确认是否有静态请求被Nginx自行处理的记录。确认collectstatic执行结果:再次检查
STATIC_ROOT目录下的文件是否完整,包括STATICFILES_DIRS中frontend/dist下的所有资源。同时确认目录及文件权限,确保uWSGI运行用户拥有读取权限。检查静态文件URL生成正确性:查看页面源码,确认
{% static %}生成的URL是否为/static/xxx格式,无域名或路径前缀错误。同时检查settings.py中USE_STATICFILES是否为True(默认开启,若被修改会导致静态文件功能失效)。
内容的提问来源于stack exchange,提问作者whitebear

