Python Django + Docker + PostgreSQL: A Clean Production-Ready Setup Guide
Dockerizing Django is one of the most important steps toward building scalable and deployable applications. This guide walks through a simple, reliable, and production-ready setup using Django, PostgreSQL, Gunicorn, and Docker Compose.
🧱 1. Recommended Project Structure
Keep your project clean and organized:
project_root/
│
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
├── .env
├── manage.py
│
├── config/
│ ├── settings/
│ ├── wsgi.py
│
└── apps/
🐳 2. Dockerfile (Django Application)
FROM python:3.12-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
RUN apt-get update && apt-get install -y \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]
🧩 3. docker-compose.yml (Django + PostgreSQL)
services:
web:
build: .
container_name: django_app
command: gunicorn config.wsgi:application --bind 0.0.0.0:8000
volumes:
- .:/app
ports:
- "8000:8000"
env_file:
- .env
depends_on:
- db
restart: always
db:
image: postgres:16
container_name: postgres_db
restart: always
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:
🔐 4. Environment Variables (.env)
SECRET_KEY=your-secret-key
DEBUG=True
DB_NAME=your_db_name
DB_USER=your_db_user
DB_PASSWORD=your_db_password
DB_HOST=db
DB_PORT=5432
⚙️ 5. Django Settings (Database Configuration)
from decouple import config
DEBUG = False
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": config("DB_NAME"),
"USER": config("DB_USER"),
"PASSWORD": config("DB_PASSWORD"),
"HOST": config("DB_HOST"),
"PORT": config("DB_PORT"),
}
}
🚀 6. Run the Project
Build and start containers
docker compose up --build
Run database migrations
docker exec -it django_app python manage.py migrate
Create superuser
docker exec -it django_app python manage.py createsuperuser
🌐 7. Access the Application
http://127.0.0.1:8000
⚠️ Common Issues & Fixes
❌ Port already in use
sudo lsof -i :8000
kill -9 <PID>
❌ PostgreSQL local conflict
sudo systemctl stop postgresql
❌ Docker compose file not found
Always run inside project directory:
cd project_root
❌ Container rebuild issues
docker compose down -v
docker compose up --build
❌ OAuth login mismatch issue
🧠 Key Takeaways
✔ Docker ensures environment consistency ✔ PostgreSQL runs as an isolated service ✔ Gunicorn is used for production WSGI serving ✔ Environment variables keep secrets safe ✔ Consistency in domain names is critical for OAuth
🚀 Final Thought
A well-structured Docker setup removes the “it works on my machine” problem and brings your Django project closer to production readiness.