See posts by tags

Setting Up a Django Development Environment Using Docker

  • 4 min read
  • 24 Jun, 2024

With the growing trend of containerization in web development, Docker has become an indispensable tool for developers. Docker allows for seamless management of dependencies and environments, enabling developers to focus on coding. In this article, we’ll guide you through setting up a Django development environment using Docker.

Prerequisites

Before starting, make sure the following are installed on your system:

  • Docker: Visit Docker’s official website to download and install Docker Desktop.
  • Docker Compose: Usually included with Docker Desktop, install separately if it’s not.

First, let’s create a folder for our project and configure the structure for the project:

/app
   /docker                 # folder for docker conf files
       nginx.conf          # conf for nginx 
       python.Dockerfile   # dockerfile for python 
   /pgdata                 # folder for postgres volumes, empty folder
   /src                    # folder where the code of your site will be
   .env                    # Configuration values for the project
   docker-compose.yml      # docker conf file with services
   requirements.txt        # a list of packages or libraries needed to work on a project
   

Step 1: Setup Python Docker Environment

Create a `.env` file using the following command:

touch .env

Enter values for your .env:

# .env

DOCKER_HTTP_PORT=80   # standart port for http
DOCKER_HTTPS_PORT=443 # standart port for https

DJANGO_PROJECT_NAME=project # the name of our Django project 

NGINX_CONF_PATH='./docker/nginx.conf' # path to nginx conf file

# DATABASE CONF
DB_USER=         # enter user name 
DB_PASSWORD=     # enter user password 
DB_DATABASE=     # enter database name 
DB_HOST=postgres # the name of postgres service in docker-compose file
DB_PORT=5432     # standart port for postgres

ADMINER_DB_PORT=8081  # port for web gui admin panel for postgres

In the docker folder, create a file named python.Dockerfile. This file defines the configuration for our Docker container. Add the following content to your python.dockerfile:

# /docker/python.Dockerfile

FROM python:3.12-alpine

ENV PYTHONUNBUFFED 1
ENV PYTHONDONTWRITEBYTECODE 1

RUN apk upgrade && apk update \
    && apk add gcc python3-dev musl-dev \
    jpeg-dev gettext zlib-dev py3-setuptools \
    mariadb-connector-c-dev mariadb-dev

RUN apk del libressl
RUN apk add openssl
RUN apk fix

#libressl-dev
RUN apk add libffi-dev cargo

RUN mkdir /app
WORKDIR /app
COPY ./src /app

COPY ./requirements.txt /app/requirements.txt

# Install any required dependencies
RUN pip install --upgrade pip && pip install -r requirements.txt

# Expose port 8000 for Gunicorn
EXPOSE 8000

This python.dockerfile creates a Docker container with Python 3.12 and installs the necessary dependencies to run a Django project.

# requirements.txt

Django
gunicorn
psycopg2-binary

Step 2: Setup Nginx Docker Environment

Create an nginx directory at the root of your project. Within it, create a default.conf file and insert the following Nginx server configuration:

# /docker/nginx.conf

# Define the upstream server (Gunicorn)
upstream web {               # name of service in docker-compose.yml
    server web:8000;         # name of service in docker-compose.yml
}

server {
    listen 80;
    server_name localhost;
    client_max_body_size 50M;
    client_body_buffer_size 50M;

    location /static/ {
        alias /static/; 
        expires 30d;
    }

    location /media/ {
        alias /media/;
        expires 30d;

    }

    location / {
        proxy_pass http://web;                # name of service in docker-compose.yml
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

}

 

Step 3: Create a Docker Compose File

In the root directory of your project, create a docker-compose.yml file. This file allows us to define and manage multi-container Docker applications. Insert the following content:

# docker-compose.yml

services:

  web:
    build: 
      context: .
      dockerfile: ./docker/python.Dockerfile
    command: gunicorn ${DJANGO_PROJECT_NAME}.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - ./src:/app:delegated
    expose:
      - 8000
    env_file:
      - .env
    restart: always


  nginx:
    image: nginx:latest
    volumes:
      - ${NGINX_CONF_PATH}:/etc/nginx/conf.d/default.conf
      - ./src/static:/static:delegated
      - ./src/media:/media:delegated
    ports:
      - "${DOCKER_HTTP_PORT}:80"
      - "${DOCKER_HTTPS_PORT}:443"
    env_file:
      - .env
    restart: always
    depends_on:
      - web

  postgres:
    image: postgres
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=${DB_DATABASE}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}

  adminer:
    image: adminer
    restart: always
    ports:
      - ${ADMINER_DB_PORT}:8080


volumes:
  pgdata:

This docker-compose.yml file creates three services: one for Python (Django), one for PostgreSQL, and one for Nginx. It also defines a Docker network that the services use to communicate.

Step 4: Build the Docker Containers

Now, we’re ready to build our Docker containers. From the root directory of your Django project, run the following command:

docker compose build

 

Step 5: Create a Django Project

We need to create a new Django project where the project name is "project" (if you change the project name, update the DJANGO_PROJECT_NAME in the .env file). Navigate to the directory where you wish to create your project and run the following command:

docker compose run --rm web django-admin startproject project .

After running this command, the project code should appear in the src folder.

If you need to run Django management commands, you can use:

docker compose run --rm web python manage.py

Run the Docker Containers

docker compose up -d

You can verify if the project is working by opening the browser and adding the port specified in DOCKER_HTTP_PORT. For example, if it’s set to 80:

http://localhost

 

6. Configure Django

Add STATIC_ROOT and configure Postgres in settings.py:

# /src/project/settings.py

import os

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

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

 

7. Run Migrations

docker compose run --rm web python manage.py migrate

Rebuild the Project Using Docker Compose

docker compose up -d --build

Create the admin user:

docker compose run --rm web python manage.py createsuperuser

After running this command, you can access the admin panel at:

http://localhost/admin

8. Handle Static Files

Add the lines for the ENTRYPOINT in the python.Dockerfile, which runs the command for static files:

# /docker/python.Dockerfile

COPY ./docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

Create /docker/entrypoint.sh file

#!/bin/sh

python manage.py collectstatic --noinput

exec "$@"

Then, restart Docker:

docker compose up -d --build

Alternatively, you can run the following command:

docker compose run --rm web python manage.py collectstatic

Access the Full Project

For the full project, feel free to visit GitHub repository