Skip to main content

Docker Development Setup

📚 Part of: Docker Guide - Return to Docker overview

Complete guide for running Django-CFG in local development with Docker Compose.


Quick Start

# Navigate to docker directory
cd docker

# Start all services
docker compose up -d

# Check status
docker compose ps

# View logs
docker compose logs -f

All services should be healthy in ~60 seconds.


Project Structure

docker/
├── docker-compose.yaml # Main compose file
├── .env # Environment variables
├── .dockerignore # Build context exclusions

├── services/ # Service-specific configs
│ ├── django/
│ │ ├── Dockerfile # Django application
│ │ ├── entrypoint.sh # Container startup
│ │ ├── config.dev.ignore.yaml # Dev API keys (in git!)
│ │ └── config.prod.ignore.yaml# Prod API keys (in git!)
│ ├── demo/Dockerfile # Next.js demo app
│ ├── websocket/Dockerfile # WebSocket RPC server
│ ├── web/Dockerfile # Nuxt.js docs site
│ └── postgres/init.sql # DB initialization

├── volumes/ # Persistent data (git-ignored)
│ ├── postgres/ # Database files
│ ├── django/media/ # User uploads
│ └── django/logs/ # Application logs

└── @docs/ # Documentation
├── README.md # Complete reference
├── CONFIG_STRATEGY.md # Configuration guide
├── DOCKER_BUILD_LESSONS.md # Build optimization
└── QUICK_REFERENCE.md # Command reference

Service Configuration

Infrastructure Services

PostgreSQL Database

Port: 5432 (internal) Databases: djangocfg (main) Extensions: uuid-ossp, pg_trgm, vector (pgvector)

postgres:
image: pgvector/pgvector:pg15
environment:
POSTGRES_DB: djangocfg
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d djangocfg"]
interval: 10s

Environment variable:

DATABASE_URL=postgresql://postgres:password@postgres:5432/djangocfg

Redis Cache & Queue

Port: 6379 (internal) Databases:

  • DB 0: Django cache
  • DB 1: ReArq task queue
  • DB 2: Centrifugo broker
redis:
image: redis:7-alpine
command: >
redis-server
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--databases 3

Environment variables:

REDIS_URL=redis://redis:6379/0
REDIS_REARQ_URL=redis://redis:6379/1

Backend Services

Django API

Port: 8300:8000 Access: http://localhost:8300

django:
build:
context: ..
dockerfile: docker/services/django/Dockerfile
environment:
DJANGO_SETTINGS_MODULE: api.settings
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/djangocfg
REDIS_URL: redis://redis:6379/0
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/cfg/health/"]
interval: 30s

Key features:

  • Auto-runs migrations on startup
  • Health check endpoint at /cfg/health/
  • Volume-mounted media files
  • Hot-reload enabled

Django ReArq Workers

Container: django-rearq Purpose: Background task processing

django-rearq:
image: djangocfg-django:latest
environment:
SKIP_MIGRATIONS: "true"
REARQ_WORKERS: 2
command: ["/entrypoint.sh", "rearq", "main:rearq", "worker"]
depends_on:
django:
condition: service_healthy

Configuration:

  • REARQ_WORKERS: Number of worker processes (default: 2)
  • Skips migrations (handled by main Django service)

WebSocket RPC Server

Ports:

  • 9065: WebSocket connections
  • 9066: Health check

Access: ws://localhost:9065

websocket:
environment:
WS_HOST: 0.0.0.0
WS_PORT: 9065
HEALTH_PORT: 9066
REDIS_URL: redis://redis:6379/2
JWT_SECRET: ${JWT_SECRET}

Frontend Services

Demo Application (Next.js)

Port: 3300 Access: http://localhost:3300

Built with Next.js standalone output for minimal image size.

Documentation Site (Nuxt.js)

Port: 3301 Access: http://localhost:3301

This documentation site you're reading now!


Traefik Reverse Proxy

Dashboard: http://localhost:8390 HTTP: Port 380 HTTPS: Port 743

Routes:

  • api.localhost:380 → Django API
  • demo.localhost:380 → Demo app
  • ws.localhost:380 → WebSocket
Access via Traefik

For a production-like experience, access services through Traefik:

http://api.localhost:380/admin/
http://demo.localhost:380

Common Development Tasks

Django Management

# Run migrations
docker exec django python manage.py migrate

# Create superuser
docker exec -it django python manage.py createsuperuser

# Django shell
docker exec -it django python manage.py shell

# Collect static files (if needed)
docker exec django python manage.py collectstatic --noinput

# Custom management command
docker exec django python manage.py your_command

Database Operations

# Access PostgreSQL shell
docker exec -it djangocfg_postgres psql -U postgres -d djangocfg

# Run SQL query
docker exec djangocfg_postgres psql -U postgres -d djangocfg -c "SELECT * FROM django_migrations LIMIT 5;"

# Backup database
docker exec djangocfg_postgres pg_dump -U postgres djangocfg > backup.sql

# Restore database
docker exec -i djangocfg_postgres psql -U postgres djangocfg < backup.sql

# Reset database (⚠️ DESTRUCTIVE)
docker exec djangocfg_postgres psql -U postgres -c "DROP DATABASE djangocfg;"
docker exec djangocfg_postgres psql -U postgres -c "CREATE DATABASE djangocfg;"
docker exec django python manage.py migrate

View Logs

# All services
docker compose logs -f

# Specific service
docker compose logs -f django

# Last 50 lines
docker compose logs --tail=50 django

# With timestamps
docker compose logs -f --timestamps django

Service Management

# Restart single service
docker compose restart django

# Stop all services
docker compose stop

# Start all services
docker compose start

# Remove all services (keeps volumes)
docker compose down

# Remove all including volumes (⚠️ DELETES DATA)
docker compose down -v

Rebuild After Changes

# Rebuild single service
docker compose build django --no-cache
docker compose up -d django

# Rebuild all services
docker compose build --no-cache
docker compose up -d

# Force recreate containers
docker compose up -d --force-recreate

Configuration

Environment Variables

Edit docker/.env:

# Database
POSTGRES_DB=djangocfg
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_password_here

# Django
DJANGO_SECRET_KEY=your-secret-key-here
DJANGO_DEBUG=true

# ReArq
REARQ_WORKERS=2

# API Keys (optional)
ANTHROPIC_API_KEY=sk-ant-your-key
OPENAI_API_KEY=sk-proj-your-key

# JWT
JWT_SECRET_KEY=your-jwt-secret-here

YAML Configuration Files

Django-CFG uses YAML files for detailed configuration:

For Docker development (team-shared API keys):

# docker/services/django/config.dev.ignore.yaml
api_keys:
openai: "sk-proj-your-team-key"
anthropic: "sk-ant-your-team-key"

email:
backend: "smtp"
host: "mail.example.com"
username: "dev@example.com"
password: "smtp-password"
Why .ignore.yaml in Git?

Docker configs with team-shared API keys are intentionally committed:

  • docker/services/django/*.ignore.yaml - Team configs (in git)
  • projects/django/api/environment/*.ignore.yaml - Personal (git-ignored)

See Configuration Strategy for details.


Service Access

ServiceURLCredentials
Django Adminhttp://localhost:8300/admin/Create with createsuperuser
Django APIhttp://localhost:8300-
API via Traefikhttp://api.localhost:380-
Demo Apphttp://localhost:3300-
Demo via Traefikhttp://demo.localhost:380-
Documentationhttp://localhost:3301-
Traefik Dashboardhttp://localhost:8390-
PostgreSQLlocalhost:5432postgres / (from .env)
Redislocalhost:6379No password

Troubleshooting

Services Won't Start

Check logs:

docker compose logs django
docker compose ps

Common issues:

  • Ports already in use → Change ports in docker-compose.yaml
  • Previous containers running → docker compose down
  • Build cache issues → docker compose build --no-cache

Configuration Not Loading

Check which config is loaded:

docker exec django python -c "from api.environment.loader import env; print(env.env.env_mode)"
# Should output: development

Verify config file exists:

docker exec django ls -la /app/api/environment/

Database Connection Failed

Check database is healthy:

docker compose ps djangocfg_postgres
docker exec djangocfg_postgres pg_isready -U postgres

Test connection:

docker exec django python manage.py check --database default

Port Already in Use

Find process using port:

lsof -i :8300

Kill process:

kill -9 <PID>

Or change port in docker-compose.yaml:

ports:
- "8301:8000" # Changed from 8300

Volume Permission Errors

Fix permissions:

sudo chown -R $USER:$USER docker/volumes/

Performance Tips

Optimize Build Speed

  1. Use .dockerignore - Already configured
  2. Layer caching - Don't change Dockerfile often
  3. BuildKit - Enable with DOCKER_BUILDKIT=1

Reduce Container Size

Images are optimized with multi-stage builds:

  • Django: ~300MB
  • Next.js demo: ~300MB (with standalone output)
  • Nuxt.js docs: ~200MB

See Build Optimization for details.

Improve Runtime Performance

# Increase workers
REARQ_WORKERS=4

# Increase Redis memory
redis:
command: redis-server --maxmemory 1gb

Next Steps

Production Deployment: Production Docker Setup →

Configuration Deep Dive: Configuration Strategy →

Build Optimization: Build Optimization Guide →

Common Issues: Troubleshooting Guide →


See Also

Docker Guides

Configuration

Getting Started


TAGS: docker, development, docker-compose, local-setup DEPENDS_ON: [docker, docker-compose, postgresql, redis] USED_BY: [development, testing, local-environment]