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

  • Avoid mixing localhost and 127.0.0.1
  • Use only one consistently across Google Cloud Console + Django


🧠 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.

To view or add a comment, sign in

More articles by sisay mineto

Explore content categories