Docker static files django not serving
I'm trying to set up my Django application in Docker with Nginx to serve static and media files, and Traefik to act as a reverse proxy. I've been struggling to get static and media files to load correctly, despite trying multiple configurations.
I want Nginx to handle static and media files while Traefik manages the reverse proxy and SSL. Below is my docker-compose.yml file.
docker-compose.yml
# PostgreSQL Database Service
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
POSTGRES_DB: ${DATABASE_NAME}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./pg_hba.conf:/var/lib/postgresql/data/pg_hba.conf
networks:
- backend-network
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U ${DATABASE_USER}" ]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
cpus: '1.0'
memory: 2G
# Redis Cache Service
redis:
image: redis:7-alpine
restart: unless-stopped
command: [ "redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}" ]
volumes:
- redis_data:/data
networks:
- backend-network
healthcheck:
test: [ "CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "PING" ]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# Django Web Application Service
web:
image: ganiyevuz/tana-backend:latest
restart: unless-stopped
command: >
/bin/bash -c "
./wait_for_db.sh db 5432 &&
python manage.py collectstatic --noinput &&
python manage.py migrate &&
gunicorn conf.wsgi:application --bind 0.0.0.0:8000 --workers 4 --threads 4
"
volumes:
- static_volume:/app/static
- media_volume:/app/media
expose:
- "8000"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
environment:
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY}
DJANGO_DEBUG: "True"
DATABASE_USER: ${DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_HOST: db
DATABASE_PORT: 5432
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
CACHE_BACKEND_URL: redis://:${REDIS_PASSWORD}@redis:6379/1
REDIS_PASSWORD: ${REDIS_PASSWORD}
ESKIZ_EMAIL: ${ESKIZ_EMAIL}
ESKIZ_PASSWORD: ${ESKIZ_PASSWORD}
ESKIZ_AUTH_URL: ${ESKIZ_AUTH_URL}
ESKIZ_SEND_URL: ${ESKIZ_SEND_URL}
OPENAI_API_KEY: ${OPENAI_API_KEY}
networks:
- backend-network
- frontend-network
- monitoring
labels:
traefik.enable: "true"
traefik.http.routers.web.rule: "Host(`${DOMAIN}`)"
traefik.http.routers.web.entrypoints: "websecure"
traefik.http.routers.web.tls.certresolver: "le"
traefik.http.services.web.loadbalancer.server.port: "8000"
traefik.http.services.web.loadbalancer.sticky: "true"
deploy:
replicas: 3
resources:
limits:
cpus: '1.0'
memory: 1G
restart_policy:
condition: on-failure
# Nginx for Serving Static and Media Files
nginx:
image: nginx:stable-alpine
restart: unless-stopped
volumes:
- static_volume:/usr/share/nginx/html/static
- media_volume:/usr/share/nginx/html/media
- ./nginx_logs:/var/log/nginx
- ./server/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- frontend-network
depends_on:
web:
condition: service_started
labels:
traefik.enable: "true"
traefik.http.routers.staticfiles.rule: "Host(`${DOMAIN}`) && (PathPrefix(`/static`) || PathPrefix(`/media`))"
traefik.http.routers.staticfiles.entrypoints: "websecure"
traefik.http.routers.staticfiles.tls.certresolver: "le"
traefik.http.services.staticfiles.loadbalancer.server.port: "80"
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
# Traefik Reverse Proxy and Load Balancer
traefik:
image: traefik:v2.10
restart: unless-stopped
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.httpchallenge=true"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.le.acme.email=ssl@${DOMAIN}"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--log.level=INFO"
- "--accesslog=true"
- "--metrics.prometheus=true"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
networks:
- frontend-network
- backend-network
- monitoring
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
labels:
traefik.enable: "true"
traefik.http.routers.traefik-dashboard.rule: "Host(`dashboard.tanahealth.uz`)"
traefik.http.routers.traefik-dashboard.entrypoints: "websecure"
traefik.http.routers.traefik-dashboard.tls.certresolver: "le"
traefik.http.services.traefik-dashboard.loadbalancer.server.port: "8080"
# Prometheus Monitoring Service
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
ports:
- "9090:9090"
networks:
- monitoring
depends_on:
- web
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
# Grafana Visualization Service
grafana:
image: grafana/grafana:latest
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
networks:
- monitoring
depends_on:
- prometheus
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# PostgreSQL Exporter for Prometheus
postgres-exporter:
image: prometheuscommunity/postgres-exporter
restart: unless-stopped
environment:
DATA_SOURCE_NAME: "postgresql://${DATABASE_USER}:${DATABASE_PASSWORD}@db:5432/${DATABASE_NAME}?sslmode=disable"
networks:
- backend-network
- monitoring
depends_on:
db:
condition: service_healthy
# Redis Exporter for Prometheus
redis-exporter:
image: oliver006/redis_exporter
restart: unless-stopped
command:
- "--redis.addr=redis:6379"
- "--redis.password=${REDIS_PASSWORD}"
networks:
- backend-network
- monitoring
depends_on:
redis:
condition: service_healthy
volumes:
postgres_data:
redis_data:
static_volume:
media_volume:
grafana_data:
networks:
frontend-network:
backend-network:
monitoring:
I’ve tried multiple ways to get static and media files working, but so far, none have succeeded. My main issues are:
Configuring Nginx to serve static and media files correctly from the Django container. Ensuring Traefik handles HTTPS and routes requests to the appropriate services (Django app for main traffic, Nginx for static/media).
Here are some specific questions I’m hoping for guidance on:
- Is the Nginx setup in my docker-compose.yml file correct for serving static and media files?
- Are the Traefik labels configured properly to handle static/media requests separately from the Django app?
Do I need any additional configuration in Django for static/media files in this setup? Thank you for any insights!