Dockerizing Django: From Development to Production
Containerization has revolutionized how we deploy web applications. As a full-stack developer, mastering Docker is no longer optional—it's a necessity. In this guide, we will take a standard Django application and package it into a container, ensuring consistency across development, testing, and production environments.
Why Docker?
Before we dive into the code, let's understand the problem Docker solves. Without containers, you rely on your host operating system's libraries. If you are on macOS and your server is Ubuntu, python versions or binary dependencies (like psycopg2) might behave differently. Docker eliminates this by packaging the OS, libraries, and code together.
Step 1: The Dockerfile
The Dockerfile tells Docker how to build your specific application image. Create a file named Dockerfile in your project root:
# Pull official base image
FROM python:3.10-slim
# Set work directory
WORKDIR /app
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Install system dependencies
RUN apt-get update && apt-get install -y netcat
# Install python dependencies
COPY requirements.txt /app/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
# Copy project
COPY . /app/
Key Directives Explained:
- FROM: We start with a lightweight Linux version containing Python.
- ENV:
PYTHONUNBUFFEREDensures Docker logs Python output immediately, vital for debugging. - WORKDIR: Sets the default directory for subsequent commands.
Step 2: Docker Compose for Services
A Django app rarely lives alone; it needs a database. We use docker-compose.yml to orchestrate multiple containers.
version: '3.8'
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=hello_django
- POSTGRES_USER=hello_django
- POSTGRES_PASSWORD=hello_django
volumes:
postgres_data:
Step 3: Connecting Django to Postgres
You must update your settings.py to point to the container service name (db), not localhost.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'hello_django',
'USER': 'hello_django',
'PASSWORD': 'hello_django',
'HOST': 'db', # This matches the service name in docker-compose
'PORT': 5432,
}
}
Running the Container
Now, lift off is simple. Run the following command in your terminal:
docker-compose up --build
Docker will download Postgres, build your Python environment, and link them via a virtual network.
Security Considerations
Never commit your .env files or passwords to GitHub. In a real production scenario, you should use Docker secrets or environment variable files not included in version control. Additionally, for production, you would swap the runserver command for a WSGI server like Gunicorn behind an Nginx proxy.
Conclusion
You now have a portable Django development environment. Whether you hand this code to a junior developer or deploy it to AWS ECS, the behavior will remain consistent.