Dockerizing Django with PostgreSQL and Nginx: A Production Hosting Guide

Dockerizing Django with PostgreSQL and Nginx: A Production Hosting Guide

Maximizing Performance and Scalability for Your Django Applications with Docker

Table of contents

Yo, so this here post is all about how you can stick your Django apps on a fancy-pants production server. We're talking Docker, baby, with PostgreSQL as our database BFF. And we're using docker-compose as our wingman, 'cause that's where we keep all our configs, ya feel me?

No need to fret! Just think of it as a fun adventure with Docker, Docker Compose, and Nginx as your trusty companions, guiding you through serving your application to the world. It's like a geek's version of a wild west showdown!

Installing Docker and Docker Compose on Ubuntu 20 is like finally having a trusty sidekick to help you handle all your containerization needs. Oh yeah!

# Update your system: 
sudo apt-get update

# Install dependencies
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

# Add Docker's official GPG key: 
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# Add the Docker repository to APT sources: 
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"

#** Update the package database: 
sudo apt-get update

# Install Docker: 
sudo apt-get install docker-ce

# Verify that the Docker service is running: 
sudo systemctl status docker

# Install Docker Compose:
sudo apt-get install docker-compose

# Verify the installation of Docker Compose: 
docker-compose --versio**n

Putting Nginx on Ubuntu 20 is like finally finding the missing puzzle piece to complete your web server's picture-perfect life!

# Update your system: 
sudo apt-get update

# Install Nginx: 
sudo apt-get install nginx

# Start the Nginx service:
sudo systemctl start nginx

# Verify that the Nginx service is running: 
sudo systemctl status nginx

# Enable Nginx to start automatically on boot: 
sudo systemctl enable nginx**

You can access the default Nginx web page by opening a web browser and navigating to localhost or the IP address of your server.

Are you bored? Nevermind

"Why did the DevOps engineer cross the road? To automate everything on the other side, of course!"

Wth is Dockerfile now?

Alright, alright, don't get your socks in a bunch. I'll try to explain what a Dockerfile is, but don't say I didn't warn you, it's a lot like trying to explain why a joke is funny... it just is!

A Dockerfile is a script that contains instructions for building a Docker image. It's like a recipe for baking a cake, but instead of flour, sugar, and eggs, you have dependencies, environment variables, and other configurations needed to run your application. Each line in the Dockerfile represents a step in the baking process, and when you bake the image, Docker follows each step and creates a delicious, ready-to-run cake...er, I mean, Docker image.

Alrighty, let's create a docker-compose file that will make your Django app dance like Gunicorn and feed it with PostgreSQL, with a side of migrations every time it gets hungry!

Here's the recipe:

version: '3'
services:
  db:
    image: postgres:12
        restart: always
        ports:
              - "5432:5432"
        volumes:
              - ./data/db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: django_db
      POSTGRES_USER: django_user
      POSTGRES_PASSWORD: django_password
  web:
    build: .
    command: bash -c "python manage.py makemigrations && python manage.py migrate && gunicorn myproject.wsgi:application --workers 3 --bind 0.0.0.0:8000"
    ports:
      - "8000:8000"
        volumes:
              - .:/code
    environment:
      DB_HOST: db
      DB_NAME: django_db
      DB_USER: django_user
      DB_PASSWORD: django_password
    depends_on:
      - db

Ahoy there matey! Are ye ready to connect yer Python Django app to PostgreSQL while havin' a good chuckle? Well, grab a parrot and let's get to it!

First off, make sure ye have the psycopg2 package installed. It's like the secret handshake between Django and PostgreSQL. Just run the following command:

pip install psycopg2

Next, we need to give Django the deets on how to talk to PostgreSQL. It's like givin' a mate the address to the pub where you'll be drinkin' a pint. And we'll use the environment variables DB_HOST, DB_NAME, DB_USER, and DB_PASSWORD to store the info:

import os

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST'),
        'PORT': '5432',
    }
}

And that's it! Yer Python Django app is now connected to PostgreSQL, ready to set sail on a wild data adventure. So hoist the main sail and let's get goin'!

And don't forget the secret ingredient, your very own Dockerfile:

FROM python:3.8
# This line is like choosing your superhero costume, only this time you're selecting Python version 3.8 as your secret identity.

ENV PYTHONUNBUFFERED=1
# This line is like telling your mom that you're going to eat your food without any distractions (buffers), so you can focus on getting all the nutrients.

WORKDIR /code
# This line is like packing your backpack with all the necessary tools and resources to start coding.

COPY requirements.txt /code/
# This line is like photocopying the ingredients for your favorite dish before cooking.

RUN pip install -r requirements.txt --no-cache-dir
# This line is like asking the chef (pip) to cook the dish you copied (requirements.txt) and making sure they don't use any leftovers from their previous meals (--no-cache-dir).

COPY . /code
# This line is like taking all your work files and putting them in your backpack, so you have everything you need to code on the go.

Now, all you need to do is mix everything together and run docker-compose up and watch your Django app twerk with Gunicorn while munching on PostgreSQL! And don't worry, the migrations will make sure your app's tummy stays happy.

Bon Appétit!

I think with these skills I can leave all the comedians jobless. It ain’t funny! I apologize for my “BAD HUMOUR”

Ladies and Gentlemen, hold on to your seats because we're about to deploy our Django app to the EC2 instance with zero downtime and a pinch of humor!

Here's the GitHub Actions file that'll make your app soar to the EC2 with zero downtime:

name: Deploy to the clouds
on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Set up SSH key
      uses: webfactory/ssh-agent@v0.4.0
      with:
        ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

    - name: Deploy to EC2 with zero downtime
      run: |
        echo "Get ready for a smooth landing, EC2! The app is coming with zero downtime!"
        ssh -o StrictHostKeyChecking=no -i ${{ secrets.SSH_PRIVATE_KEY }} ubuntu@<EC2_Instance_IP> 'docker-compose -f <docker-compose-file-location> up -d --no-deps --build web'

Now, every time you push to master, your app will take off to EC2 with zero downtime, ready to tango with Gunicorn and nibble on PostgreSQL. And the migrations will keep your app healthy and happy, just like a hot cup of tea on a cold day.

Ready for takeoff!

Arrr matey! Ye be ready to configure an Nginx reverse proxy for yer Python Django app with Certbot while adding a pinch of humor to the mix? Well, shiver me timbers, let's get to it! Grab ye favorite feathered friend and let's set sail!

sudo apt-get install certbot

Next, create a new Nginx server block configuration file for your Django app:

sudo nano /etc/nginx/sites-available/your-django-app

And add the following configuration to the file, replace the server_name with the domain name of your app and proxy_pass with the URL of yer Django app:

server {
    listen 80;
    server_name your-django-app.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Now, enable the new Nginx server block

sudo ln -s /etc/nginx/sites-available/your-django-app /etc/nginx/sites-enabled/

And then, run the Certbot tool to obtain an SSL certificate:


sudo certbot --nginx

Certbot will automatically configure Nginx to use HTTPS and redirect all HTTP traffic to HTTPS. And finally, restart Nginx to apply the changes:

sudo systemctl restart nginx

And that's it! Ye've successfully set up an Nginx reverse proxy with SSL for yer Python Django app using Certbot. So hoist the main sail and let's get goin'!

And there ye have it, folks! We've sailed through the stormy seas of technology and arrived at the port of success. Whether you're a seasoned coder or a newbie, I hope this journey was as entertaining for you as it was for me. So, let's raise a glass of grog to all the adventures yet to come! Just remember, if you're ever lost, look to the stars and keep coding! Cheers!

Did you find this article valuable?

Support Harsh Vardhan Goswami by becoming a sponsor. Any amount is appreciated!