DEV Community

Cover image for Serving Django's Static Files with Nginx
Mangabo Kolawole
Mangabo Kolawole Subscriber

Posted on • Originally published at Medium

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')
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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 . .
Enter fullscreen mode Exit fullscreen mode

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:
Enter fullscreen mode Exit fullscreen mode

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/;
    }
}
Enter fullscreen mode Exit fullscreen mode

And we are done. :)

Want to add something or have some comments? Let's discuss this in the comments section.

Article posted using bloggu.io. Try it for free.

Top comments (2)

Collapse
 
mikolajbuchwald profile image
Mikołaj Buchwald

Really well explained. + for using docker volumes. Is this example available as a git repository somewhere? For a quick "git clone" & "docker-compose up". That is usually really helpful when trying to re-create the example or adapt it to a different use case.

Collapse
 
sm0ke profile image
Sm0ke

Niceeee ...