Django+Docker+Nginx部署静态文件无法加载问题求助
api:
image: meduzzen-backend-api
container_name: django
entrypoint: ./start_prod.sh
tty: true
stdin_open: true
volumes:
- .:/code
- ./code:/apps
- static:/code/static
expose:
- "8000"
ports:
- "8000:8000"
depends_on:
- postgres-db
- redis
env_file:
- .env
networks:
- api-db-redis
...
nginx:
image: meduzzen-backend-nginx
container_name: nginx
volumes:
- static:/static
- ./nginx-conf.d:/etc/nginx/conf.d
ports:
- "80:80"
depends_on:
- api
volumes:
static:
...
#### meduzzen-backend-api 镜像的Dockerfile ```dockerfile FROM python:3.11.3-alpine ENV PYTHONBUFFERED=1 # Enable pytest-django ENV DJANGO_SETTINGS_MODULE=meduzzen_backend.settings WORKDIR /code COPY requirements.txt . RUN pip install -r requirements.txt --upgrade pip COPY . . # Copy start.sh script into project folder COPY start.sh . # Give access rights to start.sh RUN chmod +x start.sh RUN chmod +x start_prod.sh EXPOSE 8000
meduzzen-backend-nginx 镜像的Dockerfile
FROM nginx:1.25.3-alpine COPY ./default.conf /etc/nginx/conf.d/default.conf
default.conf 配置
upstream django { server api:8000; } server { listen 80; server_name localhost; location / { proxy_pass http://django; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; } location /static/ { alias /static/; add_header Access-Control-Allow-Origin *; } }
start_prod.sh 脚本内容
#!/bin/sh python manage.py migrate python manage.py collectstatic --noinput gunicorn meduzzen_backend.wsgi:application --bind 0.0.0.0:8000
问题原因及解决办法
核心原因
STATIC_ROOT与Docker卷挂载路径不匹配
Django的collectstatic会把静态文件收集到STATIC_ROOT指定的目录,如果这个目录和Docker共享卷static挂载到django容器的路径不一致,收集的文件就不会进入共享卷,Nginx自然无法读取。错误直接访问Django端口的静态资源
当DEBUG=False时,Django本身不会处理静态文件请求,所有静态资源请求必须通过Nginx转发,直接访问8000端口的静态路径必然返回404,这是正常行为,但说明你可能没走Nginx访问静态资源。静态文件权限问题
Alpine镜像的Nginx默认以nginx用户运行,如果共享卷里的静态文件权限不允许该用户读取,Nginx会返回403或404。
解决步骤
1. 对齐STATIC_ROOT与Docker卷路径
在settings.py中确保配置:
STATIC_URL = '/static/' STATIC_ROOT = '/code/static/' # 必须和django容器中static卷的挂载路径完全一致
2. 通过Nginx端口访问静态资源
不要直接访问http://localhost:8000/static/...,而是访问Nginx的80端口:http://localhost/static/admin/img/calendar-icons.svg
3. 修复静态文件权限
修改start_prod.sh,在collectstatic后添加权限设置,确保Nginx用户能读取静态文件:
#!/bin/sh python manage.py migrate python manage.py collectstatic --noinput chown -R nginx:nginx /code/static # 给静态文件目录设置可读权限 gunicorn meduzzen_backend.wsgi:application --bind 0.0.0.0:8000
4. 重启容器验证
执行以下命令重建镜像并重启服务:
docker-compose -f docker-compose-prod.yml down docker-compose -f docker-compose-prod.yml build docker-compose -f docker-compose-prod.yml up -d
内容的提问来源于stack exchange,提问作者hifichevymane

