Of course! Building a Python Django application with Docker is a standard and powerful way to ensure your application runs consistently across different environments (your laptop, a server, CI/CD pipelines).

Here is a comprehensive, step-by-step guide to containerizing a Django project.
Why Use Docker with Django?
- Consistency: "It works on my machine" becomes a thing of the past. Docker packages your application and all its dependencies (Python, libraries, database) into a portable container.
- Isolation: Your app, its dependencies, and its services (like the database) run in their own isolated environments, preventing conflicts.
- Scalability: You can easily scale your application by running multiple containers behind a load balancer.
- Simplified Deployment: Deploying to a server or a cloud platform (like AWS, Google Cloud, or Azure) is as simple as running
docker-compose up. - Local Development: You can easily replicate your production environment locally, including using the same database and services.
Prerequisites
-
Python and Django: A basic Django project. If you don't have one, you can create it:
pip install django django-admin startproject myproject cd myproject # Create a simple app for demonstration python manage.py startapp polls
-
Docker and Docker Compose: You need Docker installed on your machine.
- Install Docker Desktop (for macOS and Windows)
- Install Docker Engine (for Linux)
Step 1: Project Structure
First, let's organize our project. A common and recommended structure is to have a dedicated directory for the Docker-related files.

myproject/
├── myproject/ # Your Django project's Python package
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── polls/ # Your Django app
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations/
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── Dockerfile # Instructions to build the Docker image for your app
├── docker-compose.yml # Defines and runs multi-container Docker apps
├── .env # For environment variables (optional but good practice)
└── requirements.txt # Your Python dependencies
Step 2: Create requirements.txt
This file lists all the Python packages your project needs.
# In your project root (myproject/) pip freeze > requirements.txt
Your requirements.txt should look something like this (add psycopg2-binary for PostgreSQL):
Django==4.2.7 psycopg2-binary==2.9.9
Why psycopg2-binary? We'll use PostgreSQL as our database in the container, and psycopg2 is the popular adapter for it. The -binary version is easier to install in a containerized environment.
Step 3: Create the Dockerfile
The Dockerfile contains the instructions to build a Docker image for your Django application.

Create a file named Dockerfile in your project root:
# 1. Use an official Python runtime as a parent image
FROM python:3.11-slim
# 2. Set the working directory inside the container
WORKDIR /app
# 3. Set environment variables
# - Prevents Python from writing pyc files to disk
# - Ensures that Python output is sent straight to terminal without buffering
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# 4. Install system dependencies (if any, like for psycopg2)
# This step is often needed for packages with C extensions.
RUN apt-get update \
&& apt-get install -y --no-install-recommends gcc postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# 5. Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 6. Copy the project code into the container
COPY . .
Explanation:
FROM python:3.11-slim: We use a lightweight official Python image.slimis a smaller version of the standard image.WORKDIR /app: Sets the directory where all subsequent commands will be run.ENV ...: These environment variables help with Python's behavior inside the container.RUN apt-get ...: Installsgcc(a compiler needed by some Python packages) andpostgresql-client(a command-line tool to connect to our PostgreSQL database).COPY requirements.txt .&&RUN pip install ...: We copy therequirements.txtfile and install the dependencies. Doing this in two steps leverages Docker's layer caching. Ifrequirements.txtdoesn't change, Docker will reuse the cached layer from thepip installstep, making subsequent builds much faster.COPY . .: Copies the rest of your project code into the/appdirectory in the container.
Step 4: Set Up docker-compose.yml
docker-compose is the tool that orchestrates multiple containers. We'll use it to run our Django app, a PostgreSQL database, and (optionally) a Redis cache.
Create a file named docker-compose.yml in your project root:
version: '3.8'
services:
db:
image: postgres:15
environment:
- POSTGRES_DB=myprojectdb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data/
ports:
- "5432:5432"
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
environment:
- DEBUG=1
- DJANGO_SETTINGS_MODULE=myproject.settings
- DATABASE_URL=postgres://user:password@db:5432/myprojectdb
depends_on:
- db
# Optional: Add Redis for caching or Celery
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
Explanation:
services: Defines the containers we want to run.dbservice (PostgreSQL):image: postgres:15: Uses the official PostgreSQL 15 image.environment: Sets the database name, user, and password.volumes: Persists the database data even if the container is stopped or removed.ports: Exposes the database on port5432on your host machine.
webservice (Our Django App):build: .: Tells Docker Compose to build the image using theDockerfilein the current directory.command: The command to run after the container starts. We start Django's development server.volumes: - .:/app: This is crucial for development. It mounts your local project directory into the/appdirectory in the container. Any changes you make on your host machine are instantly reflected inside the container.ports: Exposes the Django app on port8000on your host machine.environment: Passes environment variables to the container. We setDEBUG=1and, most importantly, theDATABASE_URLwhich Django will use to connect to thedbservice. Notice we usedbas the hostname—this is the name of the service as defined indocker-compose.yml.depends_on: Ensures thedbservice is started before thewebservice.
redisservice: An optional service for caching or background task queues (like Celery).volumes: Defines a named volumepostgres_datato store the database data persistently.
Step 5: Configure Django for Docker
Now, let's tell Django to use the PostgreSQL database we defined in docker-compose.yml.
-
Install
dj-database-url: This library allows us to use a database URL string in our settings.pip install dj-database-url pip freeze > requirements.txt
-
Update
myproject/settings.py:import os from pathlib import Path import dj_database_url # Add this import # ... other settings ... # SECURITY WARNING: don't run with debug turned on in production! DEBUG = os.environ.get('DEBUG', 'False') != 'False' # ... other settings ... # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases # DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': BASE_DIR / 'db.sqlite3', # } # } # --- NEW CONFIGURATION --- # This will use the DATABASE_URL environment variable if it's set, # otherwise it falls back to a default SQLite configuration for local # development without docker-compose. if 'DATABASE_URL' in os.environ: DATABASES = { 'default': dj_database_url.parse(os.environ.get('DATABASE_URL')) } else: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } # --- END NEW CONFIGURATION --- # ... other settings ...
Step 6: Run Your Application
You're all set! Now you can build and run your entire stack with a single command.
-
Build and run the containers in detached mode:
docker-compose up --build -d
--build: Forces Docker to build the images from yourDockerfileandrequirements.txt.-d: Runs the containers in the background (detached mode).
-
Apply Migrations:
Now that the containers are running, you need to create the database tables. Open a new terminal and run:
docker-compose exec web python manage.py migrate
docker-compose exec: Executes a command in a running service.web: The name of the service (your Django app).python manage.py migrate: The Django command to create/update database tables.
-
Create a Superuser (Optional):
docker-compose exec web python manage.py createsuperuser
-
Visit Your App:
Open your web browser and navigate to
http://127.0.0.1:8000. You should see the Django welcome page.To access the admin panel, go to
http://127.0.0.1:8000/adminand log in with the superuser you created.
Step 7: Stopping and Cleaning Up
When you're done working, you can stop and remove the containers.
# Stop the containers and remove the network docker-compose down # To also remove the named volume (deleting the database data) docker-compose down -v
This guide covers the essentials of running a Django application in Docker. From here, you can explore more advanced topics like using Nginx as a reverse proxy, running Gunicorn for production, setting up environment variables with a .env file, and using Docker for your CI/CD pipeline.
