djangodockernginxdocker-composedjango-staticfiles

nginx does not seeing static files, when launching with docker compose +gunicorn


The thing is that i have set up dockerfiles, docker-compose is running everything as it should be. Databases is connected and all the staff. But the only problem is, that i cant load staticfiles. Gunicorn informs, that files "Not Found" both admin, and rest_framework static files. Even though it creates 'static' in the root directory, but doesn't collect static there, while dockerfile run.

When im doing "docker-compose up" it says that `0 static files were copied to '/static', 165 unmodified

So far i have checked paths which are configured in STATIC_ROOT and STATIC URL. Also, modified my docker-compose file:

version: '3.11'

services:
  django_gunicorn:
    volumes:
      - static:/static/
    env_file:
      - .env
    build:
      context: .
    ports:
      - "8000:8000"
  nginx:
    build: ./nginx
    volumes:
      - ./backend/service/static:/backend/static
    ports:
      - "80:80"
    depends_on:
      - django_gunicorn
      - db
  db:
    image: postgres
    expose:
      - 5432
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres
volumes:
  static:

Also i have inspected nginx config file one more time:

upstream django {
    server django_gunicorn:8000;
}

server {
    listen 80;

    location / {
        proxy_pass http://django;
    }
    location /static/ {
        autoindex on;
        alias /static/;
    }
}

i have also tried different approaches to setting up root and url of staticfiles, but left it like this for now:

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'

Also there were suggestions to run "collectstatic" first, which i have already done, but no effect, so ive deleted static folder for now, because i didnt see 'static' folder in other applications as well.

entrypoint/sh

#!/bin/sh

python manage.py migrate --no-input
python manage.py collectstatic --no-input

gunicorn config.wsgi:application --bind 0.0.0.0:8000

Here is my Dockerfile:

FROM python:3.11

RUN pip install --upgrade pip

COPY ./requirements.txt .
RUN pip install -r requirements.txt \
    python manage.py collectstatic \
    pip install python-dotenv
COPY ./backend /app

WORKDIR /app

COPY ./entrypoint.sh /
ENTRYPOINT ["sh", "/entrypoint.sh"]

Solution

  • Nginx must map STATIC_URL to STATIC_ROOT with respect to volume mapping in docker-compose.

    docker-compose volume mapping for Nginx:

    - static:/static/

    virtual volume "static" to root directory /static/

    Nginx location

    location /static/ {
        autoindex on;
        alias /static/;
    }
    

    Maps STATIC_URL = /static/ to directory inside nginx container /static/ which matches docker-compose volume mapping we just mentioned. Location is supposed to match STATIC_URL because Django is generating those URLs and it does use STATIC_URL so static files URLs will begin with STATIC_URL and to catch those URLs nginx must use the same location. But alias value is not supposed to match STATIC_ROOT because we "deliver" static files to nginx via virtual volume mapping in docker-compose and they (static files) will appear for nginx just where we tell them to - - static:/static/ - nginx container will see them under /static/ path. Django settings do not affect this path.

    Django project docker image

    COPY ./backend /app

    which means that BASE_DIR inside the container will be /app and this is exactly what collectstatic is reporting to you: '165 static files copied to '/app/static'

    now we need to share those files with nginx via virtual volume by mapping virtual volume to the directory inside django project container with collected static files. Static files were collected to /app/static. Virtual volume shared with nginx is static, so

    docker-compose volume mapping for Django project

    - static:/app/static/

    enter image description here