Django and Docker Compose

· 826 words · 4 minute read

We are going to build up on what we’ve learned so far about Docker. If you haven’t seen the previous tutorials and you are not familiar with Docker please do check them (Get started with Docker and My first Django app in Docker) to feel comfortable with today’s topic: Docker Compose.

Docker Compose vs Dockerfile 🔗

Compose is a Docker tool for building and running multi-container Docker applications. In one single YAML file you can define the different services you need to make your application run. And, with a single command (we’ll talk about this a bit later), you can run all the containers for each service from your docker-compose file.

Let’s say you want to create a containerised Django application and you want to use Postgres as your database (that’s the example we are going to look at today). You can do that in two steps:

  1. you create your Dockerfile for your Django application code, just as we have seen it in the previous post
  2. you create a docker-compose file for setting up the different services: one for the Django app itself, one for the database (and you can add more for a Redis cache or any other service you might need). In your docker-compose file, your web service (Django app) is going to depend on the postgres database service being available

Django and Dockerfile setup 🔗

Ok, let’s get into writing a bit of code. You’re now familiar with our basic setup, right?

# create a demo directory and change to it
mkdir demo && cd demo

# create a virtualenv and activate it
virtualenv ~/.virtualenvs/demo && source ~/.virtualenvs/demo/bin/activate

# install Django and psycopg2 (PostgreSQL adapter for Python)
pip install Django
pip install psycopg2

# write the current requirements to a requirements file
pip freeze > requirements.txt

# create a Dockerfile
touch Dockerfile

Open the Docker file in a text editor and add the following to it.

# use python 3.7 as a parent image
FROM python:3.7

# use unbuffered logging (no delay)
ENV PYTHONUNBUFFERED 1

# Set the working directory to /app
WORKDIR /app

# add the requirements file to the app/ directory
ADD requirements.txt /app/

# Install the packages specified in requirements.txt in the container
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Copy the local directory content into the container at /app
ADD . /app

The docker-compose file 🔗

OK, we are done with the Dockerfile. Let’s have a look at the main subject of this post, the docker-compose file. From the demo/ folder root, if you are unsure you can type pwd to double check. Good? You can do the following.

# create the docker-compose file
touch docker-compose.yml

And write the code below to the docker-compose file.

# use the docker-compose version to 3
# this is the latest version as the time of writing this post
version: '3'

# specify the services you need for your django application
services:
  # the database service uses the official postgres image for Docker
  db:
    image: postgres
  web:
    # build from the Docker file in the current directory
    build: .
    # execute the Django runserver command
    # which starts a development server
    # https://docs.djangoproject.com/en/2.1/ref/django-admin/#runserver
    command: python3 manage.py runserver 0.0.0.0:8000
    # mount the project directory (current directory) on the host to /app
    # inside the container
    volumes:
      - .:/app
    # bind the container 8000 port to localhost port 8000
    ports:
      - 8000:8000
    # make sure the db service is running before starting the web service (Django)
    depends_on:
      - db

Hopefully, the different comments helped you follow along.

The db service simply reuses the official postgres image, available on docker hub. The web service does a bit more but nothing is very new except the volumes key. The volumes key allows you to modify the code on the fly without having to rebuild the image. It is super convenient when you make modifications to your Django project and want to see the changes applied on the development server and available through your local browser immediately. If you want to go a bit further, you can read the docker documentation page on volumes.

Running your Django app locally with docker-compose 🔗

We now have ready to go Dockerfile and docker-compose files. We “just” need to create the django project and run it to check if our setup work correctly. We’ll have to modify the Django database settings because Django uses sqlite3 by default. Let’s get onto it.

# create the Django project
docker-compose run web django-admin.py startproject demoproject .

Open the demoproject/settings.py file and change the DATABASES setting to the following:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'postgres',
        'USER': 'postgres',
        'HOST': 'db',
        'PORT': 5432,
    }
}

You are now good to go and can run

docker-compose up

You can open your favorite browser and check the http://localhost:8000 page… if it all went well, you should now see the Django welcome page! Hooray, you now have a working Django app using a PostgreSQL database and everything is managed thanks to a super short docker-compose file. Congratulations :)

References 🔗