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
Try by adding the following command in Dockerfile and re-build image.
You can place it after
RUN pip install --no-cache-dir -r requirements.txt
You use a Docker named volume to hold the static files
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 runmanage.py collectstatic
in a non-Docker virtual environment.