预生产环境Nginx返回Django媒体URL 404,开发环境正常
问题分析与解决方法
核心原因
当Django的DEBUG=False时,你代码里的static(settings.MEDIA_URL, ...)不会生效——这行代码仅在开发环境(DEBUG=True)下由runserver启用,预生产环境用gunicorn启动时,Django根本没配置/media的路由,所以Nginx把/media请求转发到后端后,自然返回404。
推荐解决方案:Nginx直接托管媒体文件(生产环境最优)
Django不适合在生产环境处理静态/媒体文件,让Nginx直接serve是标准做法,步骤如下:
1. 配置Docker挂载媒体目录
在docker-compose.yml中,给Nginx服务添加媒体目录的挂载,把后端容器的MEDIA_ROOT目录映射到Nginx容器的某个路径。比如后端的MEDIA_ROOT是/app/backend/media,则Nginx的volumes配置:
services: nginx: ... volumes: - ./backend/media:/usr/share/nginx/media # 左边是本地/后端容器的媒体路径,右边是Nginx容器内的路径 - ./nginx.conf:/etc/nginx/nginx.conf backend: ... volumes: - ./backend/media:/app/backend/media # 确保后端容器能读写媒体文件
2. 修改Nginx配置
把之前合并的location ~ ^/(api|media)/拆分成两个独立的location块:
http { client_max_body_size 5M; upstream backend_api { server backend:8000; } server { listen 80; include /etc/nginx/mime.types; root /usr/share/nginx/html; index index.html; location = /favicon.ico { access_log off; log_not_found off; } # 处理API请求 location /api { proxy_pass http://backend_api; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; } # 直接托管媒体文件 location /media { alias /usr/share/nginx/media; # 对应上面挂载的Nginx容器内路径 expires 30d; # 可选,设置浏览器缓存,优化性能 add_header Cache-Control "public, max-age=2592000"; } location / { try_files $uri $uri/ /index.html; } } }
3. 验证Django配置
确保settings.py里的媒体路径配置正确:
MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 路径要和docker挂载的一致
备选方案:让Django处理媒体文件(不推荐)
如果因为某些原因必须让Django处理媒体请求,可以用whitenoise库:
- 安装whitenoise:
pip install whitenoise
- 修改settings.py:
INSTALLED_APPS = [ # 放在django.contrib.staticfiles前面 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', # 其他app... ] MIDDLEWARE = [ # 放在SecurityMiddleware之后,其他中间件之前 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', # 其他中间件... ] # 配置媒体文件处理 WHITENOISE_MEDIA_PREFIX = '/media/'
这样Django就能在DEBUG=False时处理/media请求,但性能不如Nginx直接托管,只适合小型场景。
额外检查点
- 确保媒体文件确实存在于后端的MEDIA_ROOT目录下,且文件权限正确(Nginx容器的用户能读取,比如设置目录权限为755,文件为644)。
- 重启Nginx和后端容器,确保配置生效。
内容的提问来源于stack exchange,提问作者lbris
相关产品推荐
相关产品推荐

