Deploying a Django Site Via Docker


Before you start make sure and create a requirements.txt file in your projects root folder. Also make sure you have Gunicorn installed along with your Django app. pip install gunicorn

Requirements.txt


pip freeze > requirements.txt

Dockerfile For Django APP


Next write out the Dockerfile. I stepped back once from the projects root folder. So cd ../. Then create a Dockerfile touch Dockerfile. And add the following.

FROM python:3-alpine

RUN pip install --upgrade pip

COPY ./mysite/requirements.txt .

RUN pip install -r requirements.txt

COPY ./mysite /app
WORKDIR /app
COPY ./entrypoint.sh /

ENTRYPOINT ["sh", "/entrypoint.sh"]

Entrypoint.sh


In the same directory lets write the entrypoint.sh file really quick. This will run as a last step when we build the app.

#!/bin/bash

python manage.py makemigrations --no-input
python manage.py migrate --no-input
python manage.py collectstatic --no-input

gunicorn mysite.wsgi:application --bind 0.0.0.0:8000

When you see mysite change it to the name of your project.

Nginx


We will need Nginx to proxy the container. So we will need to build an image so we can stuff a default.conf file inside of it.

So create a new directory in the same folder you created your Dockerfile from earlier. mkdir nginx then cd nginx. Now create another Dockerfile touch Dockerfile. Add the following to it.

FROM nginx:latest
COPY ./default.conf /etc/nginx/conf.d/default.conf

Next you'll need to create the default.conf file. Create the file in the nginx directory. touch default.conf.

upstream django {
    server django_gunicorn:8000;
}

server {
    listen 80;

    location / {
        proxy_pass http://django;
        # I needed to add this line in order to upload video files.
        client_max_body_size 100M;
    }

    location /static/ {
        alias /static/;
    }
    # In order to serve media files, we'll need this line
    location /media/ {
        alias /media/;
    }
}

Django Settings


Next there are some settings we'll need to change in the Django settings.py file.

import os
from dotenv import load_dotenv
load_dotenv()

# Use your .env file for this.
SECRET_KEY = os.environ.get('SECRET_KEY')
# Make sure this is set to false for production, best to set with your .env file
DEBUG = False


ALLOWED_HOSTS = ['https://yourdomainname.com']
# You will need this in order to use the Admin panel.
CSRF_TRUSTED_ORIGINS = ['https://yourdomainname.com']

# Near the bottom of the settings file add these.
STATIC_ROOT = "/static/"
STATIC_URL = "/static/"

Docker Compose


Almost to the final step. We need to create a docker-compose.yml file to glue it all together. In the directory you created your first Dockerfile, create your docker-compose.yml. touch docker-compose.yml. Add the following to it.

version: "3.7"

services:
  django_gunicorn:
    container_name: django_gunicorn
    volumes:
      - static:/static
      - media:/app/media
    env_file:
      - ./mysite/.env
    build:
      context: .
    ports:
      - "8500:8000"
  nginx:
    build: ./nginx
    volumes:
      - static:/static
      - media:/media
    ports:
      - "85:80"
    depends_on:
      - django_gunicorn

volumes:
  static:
  media:

Change the ports if need be. At this point, everything should be good to go. Just run docker-compose up --build to test it out. If you're still running on your local computer, you'll need to change ALLOWED_HOSTS to ALLOWED_HOSTS = ['*'] in your settings.py file. When everything is built you can just use docker-compose up -d.