Django + Nginx + Docker Compose in under 5 Minutes

Django + Nginx + Docker Compose in under 5 Minutes

In this post, we will see how to very quickly set up our Django development server with a Docker + Nginx setup. Disclaimer, this article is aimed at helping you get a minimal working setup of Django and Docker quickly and as such we will not be getting into much of the how's and why's of the code. So, without further ado, let's dive in.

Prerequisite

To follow this tutorial, you should have docker and docker-compose installed locally. Head over to the official documentation for steps on how to do this.

Creating and Activating the Virtual Environment

We will use the inbuilt python venv module for our virtual environment. To do so, execute the code below.

# for Linux
python3 -m venv venv
# for Windows
python -m venv venv

Activate the virtual environment with:

# linux
source venv/bin/activate
# windows
venv\Scripts\activate

Django Setup and Installing Dependencies

To install Django and the dependencies, run:

pip install django gunicorn

Gunicorn is a secure WSGI HTTP server that can be used to serve django applications.

Next, copy our environment-installed packages into a requirements.txt file.

pip freeze > requirements.txt

Now, create the Django project with the command below:

django-admin startproject django_docker_compose .

Edit your settings.py file and add a STATIC_ROOT variable. This is where all our templates, CSS, and Javascript files will be sent to when we run python manage.py collectstatic later on.

# settings.py
USE_TZ = True

STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'static' # added

Also, update the ALLOWED_HOSTS to include 127.0.0.1. This is so we can access our app from the browser later.

ALLOWED_HOSTS = ['127.0.0.1']

Setting up Docker

Here, we will specify the images we want our docker containers to run. We do this using a Dockerfile and a docker-compose file.

Creating the Dockerfile

Create a Dockerfile file at the root of the project. Note, Dockerfile has no extension.

FROM python:3.8.12-slim-bullseye

ENV PYTHONUNBUFFERED 1

ARG PROJECT_DIR=/home/app/code

WORKDIR $PROJECT_DIR

RUN useradd user && chown -R user $PROJECT_DIR

RUN python -m pip install --upgrade pip

COPY requirements.txt $PROJECT_DIR

RUN pip3 install --no-cache-dir -r requirements.txt

COPY . $PROJECT_DIR

RUN python manage.py collectstatic

USER user

Creating the Docker Compose File

Create a docker-compose.yml file at the root of the project.

version: '3.6'
services:
  nginx:
    build: 
      context: ./nginx 
    ports: 
    - 80:80 
    volumes:  
      - static_volume:/home/app/code/static
    depends_on:
      - web 
    restart: "on-failure"
  web:
    build: 
      context: .
    command: sh -c "python manage.py migrate &&
                    gunicorn django_docker_compose.wsgi:application --bind 0.0.0.0:8000 --reload" 
    volumes: 
      - ./:/code
      - static_volume:/home/app/code/static
    image: web
    restart: "on-failure"

volumes:
  static_volume:

At a high level, we are creating two containers: web, our Django server, and Nginx, our reverse proxy server. We will serve our Django static files with Nginx.

To make this compose file work, we need to create a new directory nginx at the root of the project and inside it, we create two new files:

  1. Dockerfile (This will specify how we want our Nginx service image to be built.)

  2. nginx.conf (Configuration file for our Nginx server.)

Inside nginx/Dockerfile, paste the following:

FROM nginx:1.23

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

Inside nginx/nginx.conf, paste the following:

server {

    listen 80 default_server;

    location / {
        proxy_pass http://web:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }
    location /static/ {
        alias /home/app/code/static/;
    }
}

The nginx.config file specifies where our static files are stored and routes other requests to our web service.

Now build the images and run the containers. To do this, run:

docker-compose up --build

With this, you should have your development server running. Head over to http://127.0.0.1 to check it out.

...And that's it🎉. We have very quickly set up docker, docker-compose, and a reverse proxy server for our Django application.

Further Learning

For more detailed tutorials, you can checkout the following articles

  1. Introduction to Elastic Beanstalk with Django, RDS, Docker, and Nginx at MoreAboutTech.

  2. Dockerizing Django with Postgres, Gunicorn, and Nginx at TestDriven.

  3. Dockerizing Django App at LogRocket.


If you found this article useful or learned something new, consider dropping a heart up and following me here on hashnode to keep up-to-date with any recent postings!

If there are certain topics you would also like me to cover and/or questions you may have, do drop a comment.

You can also find me on Twitter at akinsola232 and on LinkedIn at Ademola.

Till next time, happy coding!