Cookiecutter-Django替换Caddy为Nginx后静态文件无法加载求助
Let's get your static files working properly with Nginx. The core issue here is that your Nginx container needs reliable access to the static files generated by Django's collectstatic command, which runs inside the Django container. Your previous attempts with volumes_from or copying the project might have hit permission issues or sync problems—here's the clean, maintainable fix:
Step 1: Use a Shared Volume for Static Files
Instead of trying to share the entire Django container's filesystem, create a dedicated Docker volume to store static files. This keeps things isolated and avoids permission conflicts.
Update your production.yml Docker Compose config:
# Add this at the bottom of the file to define the shared volume volumes: static_files: {} # Update the django service to mount this volume to STATIC_ROOT django: # ... keep your existing config (build, env_file, etc.) volumes: - static_files:/app/staticfiles # Matches Django's STATIC_ROOT (default in Cookiecutter-Django) # Update the nginx service to mount the same volume nginx: build: context: . dockerfile: ./compose/production/nginx/Dockerfile image: abs_production_nginx depends_on: - django ports: - "0.0.0.0:80:80" env_file: - ./.envs/.production/.nginx volumes: - static_files:/app/staticfiles # This path needs to match the alias in your Nginx config
Step 2: Tweak Your Nginx Configuration
Make sure your Nginx config points to the correct path where the shared volume is mounted, and add proper caching headers for static files (good practice for production):
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; upstream app { server django:5000; } server { listen 80; charset utf-8; # Serve static files directly from the shared volume location /static { alias /app/staticfiles; expires 30d; # Cache static files for 30 days add_header Cache-Control "public, immutable"; # Tell browsers to cache aggressively } # If you need to serve media files (user uploads), add this too # Make sure to create a shared media volume similar to static_files if needed location /media { alias /app/media; expires 7d; add_header Cache-Control "public"; } location / { try_files $uri @proxy_to_app; } location @proxy_to_app { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://app; } } }
Step 3: Verify Permissions and Collectstatic
- Cookiecutter-Django runs the Django container with a non-root user (usually
django), but the shared volume will be writable by this user since it's mounted directly. - Ensure your Django container runs
collectstaticon startup—Cookiecutter-Django's default production entrypoint should already handle this, but double-check yourcompose/production/django/entrypointscript to confirm it includespython manage.py collectstatic --noinput.
Why Your Previous Attempts Didn't Work
volumes_from: - django: This shares all volumes from the Django container, but the Nginx user (nginx) might not have read permissions on the files owned by the Django container's user (django), leading to 403 errors.- Copying the project to Nginx: This is redundant because
collectstaticgenerates files after the Django container starts, so the copied files would be outdated or missing entirely.
内容的提问来源于stack exchange,提问作者Arti

