skip to Main Content

I am building a Django app with Docker. I run the command collectstatic in my entrypoint when database is ready. When I check my container, the /static/ folder is empty. Thus, Nginx cannot load the static files.

# settings.py
STATIC_URL = '/static/'
STATIC_ROOT = '/static/'

Here is my docker-compose file

version: "3.9"

services:
  db:
    image: postgis/postgis:14-3.3
    container_name: db
    volumes:
      - ./data/db:/var/lib/postgresql/data
    env_file:
    - prod.env

  backend:
    container_name: backend
    build:
      dockerfile: ./django/Dockerfile
    command: gunicorn api.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - static:/usr/src/app/static
    ports:
      - "8000:8000"
    env_file:
    - prod.env
    depends_on:
      - db
  
  nginx:
    container_name: nginx
    build:
      dockerfile: ./nginx/Dockerfile
    volumes:
      - static:/usr/src/app/static
    ports:
      - "80:80"
    depends_on:
      - backend
    restart: always

  redis:
    container_name: redis
    restart: unless-stopped
    image: redis:alpine 
    expose:
      - 6379

  worker:
    container_name: worker
    build:
      dockerfile: ./django/Dockerfile
    command: celery -A api worker -l INFO
    volumes:
      - static:/usr/src/app/static
    env_file:
    - prod.env
    depends_on:
      - db
      - backend
      - redis
  
volumes:
  static:

My Nginx configuration:

upstream api {
    server backend:8000;
}

server {
    listen 80;

    location / {
        proxy_pass http://api;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /static/ {
        alias /usr/src/app/static/;
    }
}

backend Dockerfile:

# syntax=docker/dockerfile:1
FROM python:3
WORKDIR /usr/src/app
RUN apt-get update
RUN apt-get install -y libgdal-dev gdal-bin netcat

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
COPY /django/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY /django/django-entrypoint.sh /django-entrypoint.sh
RUN chmod +x /django-entrypoint.sh

COPY django /usr/src/app

ENTRYPOINT ["/django-entrypoint.sh"]

And the entrypoint:

#!/bin/sh

if [ "$POSTGRES_NAME" = "postgres" ]
then
    echo "Waiting for Postgres..."

    while ! nc -z $POSTGRES_HOST $POSTGRES_PORT; do
      sleep 0.1
    done

    echo "PostgreSQL started"
fi

ls
# python manage.py flush --no-input
python manage.py migrate --no-input
python manage.py collectstatic --no-input

exec "$@"

In my files (local), I do not seem to see the ‘/static/’ folder to be generated. How is this? I have check that static in backend and nginx by ssh in the container and the static folders were empty. In the logs, collectstatic was executed without an error with this message:

backend | 173 static files copied to ‘/static’.

2

Answers


  1. Try by adding the following command in Dockerfile and re-build image.

    RUN python manage.py collectstatic --noinput
    

    You can place it after RUN pip install --no-cache-dir -r requirements.txt

    Login or Signup to reply.
  2. You use a Docker named volume to hold the static files

        volumes:
          - static:/usr/src/app/static
          # ^^^^^^
          #   a volume name, not a host path
    

    This named volume only exists inside Docker’s storage; you will not see its content on your host system or in your local source tree.

    This isn’t a problem for the setup you’re describing here: since you’re re-running collectstatic every time the container starts up, and the volume contents hide the image contents in this directory, there’s no particular need for the files to exist in source control or your host filesystem. If you did need them, you could presumably run manage.py collectstatic in a non-Docker virtual environment.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search