How to do it...

Let's explore the Django and Docker boilerplate:

  1. Download the code from https://github.com/archatas/django_docker to your computer to the ~/projects/django_docker directory, for example.
If you choose another directory, for example, myproject_docker, then you will have to do a global search and replace  django_docker with myproject_docker.
  1. Open the docker-compose.yml file. There are three containers that need to be created: nginx, gunicorn, and db. Don't worry if it looks complicated; we'll describe it in detail later:
# docker-compose.yml
version: "3.7"

services:
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./config/nginx/conf.d:/etc/nginx/conf.d
- static_volume:/home/myproject/static
- media_volume:/home/myproject/media
depends_on:
- gunicorn

gunicorn:
build:
context: .
args:
PIP_REQUIREMENTS: "${PIP_REQUIREMENTS}"
command: bash -c "/home/myproject/env/bin/gunicorn --workers 3
--bind 0.0.0.0:8000 myproject.wsgi:application"
depends_on:
- db
volumes:
- static_volume:/home/myproject/static
- media_volume:/home/myproject/media
expose:
- "8000"
environment:
DJANGO_SETTINGS_MODULE: "${DJANGO_SETTINGS_MODULE}"
DJANGO_SECRET_KEY: "${DJANGO_SECRET_KEY}"
DATABASE_NAME: "${DATABASE_NAME}"
DATABASE_USER: "${DATABASE_USER}"
DATABASE_PASSWORD: "${DATABASE_PASSWORD}"
EMAIL_HOST: "${EMAIL_HOST}"
EMAIL_PORT: "${EMAIL_PORT}"
EMAIL_HOST_USER: "${EMAIL_HOST_USER}"
EMAIL_HOST_PASSWORD: "${EMAIL_HOST_PASSWORD}"

db:
image: postgres:latest
restart: always
environment:
POSTGRES_DB: "${DATABASE_NAME}"
POSTGRES_USER: "${DATABASE_USER}"
POSTGRES_PASSWORD: "${DATABASE_PASSWORD}"
ports:
- 5432
volumes:
- postgres_data:/var/lib/postgresql/data/

volumes:
postgres_data:
static_volume:
media_volume:

  1. Open and read through the Dockerfile file. These are the layers (or instructions) that are needed to create the gunicorn container:
# Dockerfile
# pull official base image
FROM python:3.8

# accept arguments
ARG PIP_REQUIREMENTS=production.txt

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install dependencies
RUN pip install --upgrade pip setuptools

# create user for the Django project
RUN useradd -ms /bin/bash myproject

# set current user
USER myproject

# set work directory
WORKDIR /home/myproject

# create and activate virtual environment
RUN python3 -m venv env

# copy and install pip requirements
COPY --chown=myproject ./src/myproject/requirements /home/myproject/requirements/
RUN ./env/bin/pip3 install -r /home/myproject/requirements/${PIP_REQUIREMENTS}

# copy Django project files
COPY --chown=myproject ./src/myproject /home/myproject/
  1. Copy the build_dev_example.sh script to build_dev.sh and edit its content. These are environment variables to pass to the docker-compose script:
# build_dev.sh
#!/usr/bin/env bash
DJANGO_SETTINGS_MODULE=myproject.settings.dev \
DJANGO_SECRET_KEY="change-this-to-50-characters-long-
random-string"
\
DATABASE_NAME=myproject \
DATABASE_USER=myproject \
DATABASE_PASSWORD="change-this-too" \
PIP_REQUIREMENTS=dev.txt \
docker-compose up --detach --build
  1. In a command-line tool, add execution permissions to build_dev.sh and run it to build the containers:
$ chmod +x build_dev.sh
$ ./build_dev.sh
  1. If you now go to http://0.0.0.0/en/, you should see a Hello, World! page there.
    When navigating to http://0.0.0.0/en/admin/, you should see the following:
OperationalError at /en/admin/
FATAL: role "myproject" does not exist

This means that you have to create the database user and the database in the Docker container.

  1. Let's SSH to the db container and create the database user, password, and the database itself in the Docker container:
$ docker exec -it django_docker_db_1 bash
/# su - postgres
/$ createuser --createdb --password myproject
/$ createdb --username myproject myproject

When asked, enter the same password for the database as in the build_dev.sh script.

Press [Ctrl + D] twice to log out of the PostgreSQL user and Docker container.

If you now go to http://0.0.0.0/en/admin/, you should see the following:

ProgrammingError at /en/admin/ relation "django_session" does not exist LINE 1: ...ession_data", "django_session"."expire_date" FROM "django_se...

This means that you have to run migrations to create the database schema.

  1. SSH into the gunicorn container and run the necessary Django management commands:
$ docker exec -it django_docker_gunicorn_1 bash
$ source env/bin/activate
(env)$ python manage.py migrate
(env)$ python manage.py collectstatic
(env)$ python manage.py createsuperuser

Answer all the questions that are asked by the management commands.

Press [Ctrl + D] twice to log out of the Docker container.

If you now navigate to http://0.0.0.0/en/admin/, you should see the Django administration, where you can log in with the super user's credentials that you have just created.

  1. Create analogous scripts, build_test.sh, build_staging.sh, and build_production.sh, where only the environment variables differ.