Kolawole Mangabo

Serving Django's Static Files with Nginx.

You have developed an excellent Django application, and it’s time to deploy.

You are going for NGINX - a great choice - but your Django project has actually configurations for static files. Given that the Django application will be running through NGINX, it’s important to have static files configured and served via NGINX.

Django static files configuration

If you are not familiar with Django static files, you can read a small article I’ve written here.

Here’s the Django configuration for a simple project.

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]
STATIC_ROOT =  os.path.join(BASE_DIR, 'staticfiles')

In the deployment process, it’s essential to ensure that the python manage.py collectstatic command has run. When using this command, Django looks for all static files in the apps and collects them in the STATIC_ROOT path, then in the staticfiles.

NGINX webserver configuration file

sudo nano /etc/nginx/sites-enabled/django-app.conf

Inside the django-app.conf file, we need to add a location for the staticfiles in the Django project.

location /static/{
    autoindex on;
    alias /home/app/django-app/staticfiles/; // => the path to the static folder
}

After that, reload the NGINX server, and you are good to go.

This solution is a little bit long and not automated. Most of the time, I just use Docker, and I just move the code from another machine to another one and start the containers.

Serving static files with NGINX and Docker

With the same settings of the Django application, let’s write a docker-compose.yaml file containing the same configuration to serve static files.

Basically, we need two services:

  • The Django application.
  • And the NGINX server.

Here’s what the Dockerfile will look like first. This Dockerfile will be built and used as the image of the Django application service.

# pull official base image
FROM python:3.10-alpine

# set work directory
WORKDIR /app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apk update \
    && apk add gcc python3-dev

# install python dependencies
COPY requirements.txt /app/requirements.txt
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt


# copy project
COPY . .

And here’s an example of static files.

version: '3.9'
services:
  nginx:
    container_name: core_web
    restart: on-failure
    image: nginx:stable
    volumes:
      - ./nginx/nginx.dev.conf:/etc/nginx/conf.d/default.conf
      - static_volume:/staticfiles
    ports:
      - "80:80"
    depends_on:
      - api
  api:
    container_name: core_app
    build: .
    restart: always
    env_file: .env
    ports:
      - "5000:5000"
    command: >
      sh -c " python manage.py migrate &&
          gunicorn CoreRoot.wsgi:application --bind 0.0.0.0:5000"      
    volumes:
     - .:/app
     - static_volume:/staticfiles

volumes:
  static_volume:

And also, update the Nginx configuration file to route static file requests to the staticfiles folder.


upstream webapp {
    server core_app:5000;
}
server {

    listen 80;
    server_name localhost;

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

    location /static/ {
       autoindex on;
       alias /home/app/django-app/staticfiles/;
    }
}

And we are done. :)

Want to add something or have some comments? Feel free to contact me on Twitter or via email.