Docker+Nginx部署Django时无法加载静态文件的问题排查
Django+Docker+Nginx部署静态文件加载失败问题
Docker部署Django应用搭配Nginx反向代理,应用本身可正常访问,但静态文件返回404错误,推测问题出在卷路径或Nginx配置上。
目录结构
- nginx -- default.conf -- Dockerfile - portfolio_app (Django项目) -- main_app --- settings.py --- wsgi.py -- sub_app --- views.py --- static --- media - docker-compose.yml - Dockerfile (Django相关) - entrypoint.sh (启动Django服务脚本)
Django相关配置
Dockerfile
FROM python:3.8.13-slim-buster WORKDIR /app RUN pip install --upgrade pip COPY ./requirements.txt ./ RUN pip install -r requirements.txt COPY ./portfolio_app ./ COPY ./entrypoint.sh ./ ENTRYPOINT ["sh","/app/entrypoint.sh"]
settings.py 静态文件配置
MEDIA_ROOT = os.path.join(BASE_DIR, 'sub_app','media') MEDIA_URL = '/media/' STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'sub_app','static')
Nginx相关配置
default.conf
upstream django { server portfolio_application:8000; } server { listen 80; location / { proxy_pass http://django; } location /static/ { alias /static_volume/; } }
Nginx Dockerfile
FROM nginx:1.19.0-alpine COPY ./default.conf /etc/nginx/conf.d/default.conf
docker-compose.yml
version: '3.3' services: portfolio_application: build: context: . container_name: portfolio_app volumes: - static_volume:/app/sub_app/static - media_volume:/app/sub_app/media ports: - "8000:8000" env_file: - .env nginx: build: ./nginx volumes: - static_volume:/app/sub_app/static - media_volume:/app/sub_app/media ports: - "80:80" depends_on: - portfolio_application volumes: media_volume: static_volume:
日志信息
Attaching to portfolio_app, docker_nginx_1 portfolio_app | [2022-07-21 09:22:10 +0000] [7] [INFO] Starting gunicorn 20.1.0 nginx_1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration nginx_1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ portfolio_app | [2022-07-21 09:22:10 +0000] [7] [INFO] Listening at: http://0.0.0.0:8000 (7) portfolio_app | [2022-07-21 09:22:10 +0000] [7] [INFO] Using worker: sync nginx_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh portfolio_app | [2022-07-21 09:22:10 +0000] [9] [INFO] Booting worker with pid: 9 nginx_1 | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf nginx_1 | 10-listen-on-ipv6-by-default.sh: /etc/nginx/conf.d/default.conf differs from the packages version, exiting nginx_1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh nginx_1 | /docker-entrypoint.sh: Configuration complete; ready for start up nginx_1 | 172.19.0.1 - - [21/Jul/2022:09:22:13 +0000] "GET / HTTP/1.1" 200 48080 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0" "-" nginx_1 | 2022/07/21 09:22:13 [error] 29#29: *1 open() "/static_volume/lib/animate/animate.min.css" failed (2: No such file or directory), client: 172.19.0.1, server: , request: "GET /static/lib/animate/animate.min.css HTTP/1.1", host: "0.0.0.0", referrer: "http://0.0.0.0/" nginx_1 | 172.19.0.1 - - [21/Jul/2022:09:22:13 +0000] "GET /static/lib/animate/animate.min.css HTTP/1.1" 404 153 "http://0.0.0.0/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0" "-"
问题分析与修复步骤
从日志可明确看到,Nginx尝试访问/static_volume/lib/animate/animate.min.css但找不到文件,核心问题是Nginx配置的静态文件路径与实际卷挂载路径不匹配,同时需确保Django已将静态文件收集到指定目录。
修复方案二选一:
方案1:调整Nginx配置匹配卷挂载路径
修改nginx/default.conf中的静态文件location配置,将alias指向Nginx容器内的静态卷路径,同时补充媒体文件的location配置:
location /static/ { alias /app/sub_app/static/; } location /media/ { alias /app/sub_app/media/; }
方案2:调整卷挂载路径匹配Nginx配置
修改docker-compose.yml中Nginx服务的volumes配置,将静态卷挂载到/static_volume,媒体卷挂载到/media_volume:
nginx: build: ./nginx volumes: - static_volume:/static_volume - media_volume:/media_volume ports: - "80:80" depends_on: - portfolio_application
关键补充:确保Django收集静态文件
修改entrypoint.sh,在启动Gunicorn之前执行collectstatic命令,确保静态文件被收集到STATIC_ROOT(即卷挂载的目录):
#!/bin/sh # 收集静态文件,--noinput避免交互确认 python manage.py collectstatic --noinput # 启动Gunicorn服务 gunicorn main_app.wsgi:application --bind 0.0.0.0:8000
内容的提问来源于stack exchange,提问作者Talha Anwar
相关产品推荐
相关产品推荐

