Dockerizing Django: A Step-by-Step Guide for Dockerizing Your Django Project

Guide to Dockerizing Django! In this article, we'll guide you through the steps of containerizing your Django project, using Docker to optimize your development and deployment procedures.

April 26, 20247 min read

Introducing Docker to your Django project can significantly enhance its scalability, portability, and ease of deployment. In this step-by-step guide, we will explore the process of Dockerizing a Django project, allowing you to encapsulate your application and its dependencies within lightweight, portable containers. A major compelling argument for utilizing Docker is that it entirely eliminates any concerns with local development setup. Instead of worrying about which software packages are installed or running a local database alongside a project, you use a Docker image that contains the complete project. Best of all, this can be shared in groups, which simplifies team growth. Let's dive in!

Prerequisite

  • Docker Installed
  • Docker Compose

Let's make sure Docker and Docker Compose are installed on your machine before we start Dockerizing our Django app. On both the Mac and Windows operating systems, Docker automatically includes Docker Compose as an extra tool. However, Docker Compose requires a separate installation for Linux users. Once Docker is installed, you may accomplish this by using the command

sudo pip install docker-compose

We can verify that the right version of Docker is running once the installation is complete. Type the command docker --version into your terminal.

Use Ctl+C to end the local server, and then enter docker run hello-world in the command window to verify the installation was successful. This is what you ought to see in response:

Image

Docker is now properly installed.

Project Setup

On this project, I will be using Ubuntu.

# Linux
$ cd ~/Django-docker-project
$ mkdir docker-djangov1

THEN:
$ python3 -m venv venv
$ source venv/bin/activate

$ python3 -m pip install django


Let us create our new project;

(venv) $ django-admin startproject django_project .
(venv) $ python manage.py runserver

To Confirm everything worked by navigating to http://127.0.0.1:8000/ in your web browser

It's time to move to Docker now but before we deactivate and leave our virtual environment as we no longer need it, lets create requirements.txt which includes Django and packages that comes with it

(venv) $ pip freeze > requirements.txt

Image

(venv) $ deactivate

$

Try Kodaschool for free

Click below to sign up and get access to free web, android and iOs challenges.

Sign Up

Docker Image

Think of Docker images as recipe cards for baking cakes. Each recipe card contains all the instructions and ingredients needed to bake a specific type of cake. Similarly, Docker images contain all the instructions and dependencies required to run a specific application. Just like you can use the same recipe card to bake multiple cakes, you can use the same Docker image to create multiple containers running the same application. This ensures consistency and reproducibility across different environments, much like how following a recipe ensures consistent results when baking cakes.

A Docker image is a read-only template that specifies how to build a Docker container. The image contains the instructions, whereas the container is the actual running instance of the image.

At the root of our project, we need to create a custom image for our Django project that includes Python, as well as our code and extra configuration information. To generate our image, we create a file called a Dockerfile - with no extension, which outlines the procedures for creating and running the customized image.

Dockerfile

# FROM python:3.11.5-slim-bullseye
# Use the Python 3.11.5 slim image based on Debian "Bullseye" as the base image.

# Set environment variables
ENV PIP_DISABLE_PIP_VERSION_CHECK 1
# Set an environment variable to disable checking for newer versions of pip.
ENV PYTHONDONTWRITEBYTECODE 1
# Set an environment variable to prevent Python from writing bytecode files (e.g., .pyc files).
ENV PYTHONUNBUFFERED 1
# Set an environment variable to ensure Python prints directly to stdout/stderr without buffering.

# Set work directory
WORKDIR /code
# Set the working directory inside the container to /code.

# Install dependencies
COPY ./requirements.txt .
# Copy the requirements.txt file from the local directory to the /code directory inside the container.
RUN pip install -r requirements.txt
# Run the pip command inside the container to install the Python dependencies specified in requirements.txt.

# Copy project
COPY . .
# Copy the entire project directory from the local directory to the /code directory inside the container.

.dockerignore file

It is advised that you create a.dockerignore file to prevent particular files and directories from being included in a Docker image. This optimizes image size and improves security by preventing sensitive information from being accidentally included. For example, we can disregard the local virtual environment (venv), .git directory, and .gitignore file. To create the .dockerignore file, open your text editor and add a new file named .dockerignore to the base directory, beside the current manage.py file.

# .dockerignore file
.gitignore
venv/
.git

We have provided detailed instructions for creating a custom image, but the construction process has not yet begun. To start the build, use the command docker build, followed by a period; $ docker build . - this period refers to the Dockerfile in the current directory. Expect to see a lot of output during this procedure. I've posted the first two lines and the final one here for your convenience.

$ docker build .
[+] Building 9.1s (10/10) FINISHED
 => [internal] load build definition from Dockerfile
...
=> => writing image sha256:89edeuy7w...

Now that our custom image is complete, we can run it as a container. To do this, we need a set of instructions saved in a file called docker-compose.yml. Using your choice text editor, create a docker-compose.yml file in the project-level directory, next to the Dockerfile. This file will contain the following code snippet.

# docker-compose.yml

# Define the services to be managed by Docker Compose
services:
  # Define a service named "web"
  web:
    # Specify the build context for this service (current directory)
    build: .
    # Expose ports for the service (host:container)
    ports:
      - "8000:8000"
    # Specify the command to run within the container
    command: python manage.py runserver 0.0.0.0:8000
    # Mount a volume to allow live code updates without rebuilding the container
    volumes:
      - .:/code

We specify the services or containers, we wish to operate within our Docker host. While numerous services can operate at the same time, we'll focus on one called "web" for the time being. Within the "web" service, we specify the build context by setting the build option to look in the current directory for our Dockerfile. We'll utilize the default Django ports, configuring port mapping to expose port 8000 on the host and container. Additionally, we define the command to execute, which in this case, starts the local web server using the Django management command python manage.py runserver 0.0.0.0:8000.

Finally, we utilize the volumes option to automatically mount the Docker filesystem to our local computer's filesystem. This ensures that any changes made within the Docker container are automatically synced with the local filesystem, facilitating seamless development. For instance, if we modify the code within the Docker container, those changes will be reflected in the local filesystem.

To complete the process, we execute the command docker-compose up, initiating the Docker container. Expect to see a lengthy output stream on the command line, detailing the container setup and execution.

To confirm if everything is working go to http://127.0.0.1:8000/ in your web browser. Django is now running purely within a Docker container.

Image

NOTE: Before proceeding further, ensure that the currently running container is stopped. You can accomplish this by pressing "Control" and "c" simultaneously (Control+c) to stop the container. Additionally, type docker-compose down in your terminal. It's important to stop Docker containers when they are no longer in use, as they can consume a significant amount of system memory. Remember that Docker containers are designed to be stateless, so we utilize volumes to synchronize our code locally, allowing it to be preserved and easily accessed.

HAPPY CODING!

Rodgers Mokaya

About Rodgers Mokaya

I am a Software Developer and a technical writer I enjoy using my skills to contribute to the exciting technological advances that happen every day.