Dockerizing Django With Postgres, NGINX, and Gunicorn (PART-1)

Dockerizing Django With Postgres, NGINX, and Gunicorn (PART-1)

We will be discussing about the Dockerizing Django project for the deployment

Running a Django application in a production environment requires a server that can handle traffic, ensure stability, and provide scalability. Gunicorn is a widely used and trusted server for running Django applications in such an environment. In this article, we'll be deploying a Django application with docker, postgres, gunicorn and nginx configurations. So, Let's start and understand everything in more detail step by step

Prerequisites

Before we begin, make sure that you have the following installed on your local machine:

  • Python 3.7 or higher

  • Django

  • Django Rest Framework

  • Docker and Docker-compose

Make sure to set up your Django project and run it locally. After everything is ready, let's make your Django application ready for deployment.

Create a Dockerfile

The Dockerfile is a script that contains instructions on how to build a Docker image for your application. Create a new file named Dockerfile in the root directory of your Django project with the following content:

# official base image
FROM python:3.10.9-alpine3.17

#set work directory
RUN mkdir /app
WORKDIR /app

#set environment variable
ENV PYTHONDONTWRITEBYCODE 1
ENV PYTHONUNBUFFERED 1

#install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# copy project
COPY . .

Let's understand the code Line by Line,

So basically, The first line specifies the official base image to use, which is the Python 3.10.9-alpine3.17 image. This image is a lightweight version of Python that runs on Alpine Linux, which is a small, secure, and efficient Linux distribution.

Next, the working directory is set to /app, which is where the application code will reside inside the container.

Two environment variables are set to ensure that the Python application runs correctly in the container. The PYTHONDONTWRITEBYCODE environment variable is set to 1, which instructs Python not to write bytecode files to disk. The PYTHONUNBUFFERED environment variable is also set to 1, which disables the buffering of standard output and standard error streams by Python.

The dependencies for the Django application are installed via pip. First, pip is upgraded to the latest version, and then the contents of requirements.txt are copied into the container and installed using pip.

Finally, the entire contents of the application's directory are copied into the Docker image. This includes the Django project files, any static files, templates, or media files, as well as any other necessary files for the application to run.

This Dockerfile sets up the basic environment required to run a Django application in a containerized environment and is a good starting point for building more complex Docker images for Django applications.

Let's go on more,

Docker Compose

Docker Compose is a tool that allows you to define and run multi-container Docker applications. With Compose, you can define the services that make up your application, how they should be configured, and how they should interact with each other.

A Docker Compose file is a YAML file that defines the services, networks, and volumes required for your application. In a typical Django application, you might have several services, such as the Django web server, a database service like Postgres, and a web server like Nginx.

In a Docker Compose file, you would define each of these services as a separate container, along with their configuration options. You can also define networks and volumes that are shared between the containers.

So Let's Make a docker-compose.yml file to the root project

version: '3.10'

services:
    app:
        build: .
        command: python manage.py runserver 0.0.0.0:8000
        volumes:
            - static_data:/app/static
        ports:
            - "8000:8000"
        env_file:
            - ./.env

Let's understand the code line by line,

The command instruction specifies the command to run when the container starts up. In this case, it's running the runserver command for Django, which starts a development server that listens on all available network interfaces (0.0.0.0) on port 8000.

The volumes instruction creates a named volume named static_data that will be mounted inside the container at the path /app/static. This allows the container to access static files that are generated by Django and stored outside of the container.

The ports instruction maps port 8000 on the host machine to port 8000 inside the container, so that the Django application can be accessed by visiting http://localhost:8000 in a web browser.

Finally, the env_file instruction specifies a path to a file containing environment variables that should be loaded into the container. In this case, the file is located at ./.env.

Now, create a .env file in the project root to store environment variables for development:

SECRET_KEY=
ALLOWED_HOSTS= localhost 127.0.0.1 [::1]
DEBUG=True

You need to change the SECRET_KEY, ALLOWED_HOST and DEBUG in your project Setting file. Make sure to add import os in your setting file

import os
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', default=False, cast=bool)

ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())

Now, Build the image:

$ docker-compose build

Once the image is built, run the container:

$ docker-compose up -d

Now Go to http://localhost:8000/ to see the project running.

Summary:

Up to now We built a Docker image of our application and run into a container that is running successfully. In the next part, We'll see how to integrate PostgreSQL with your application and dockerize further until then have a great time. Bye!

Part-2: Dockerizing Django With Postgres, NGINX, and Gunicorn (PART-2)