BackendDeployment
Docker
Docker Compose setup for local development and production.
Local Development
Build & Start
# Build all services
docker compose -f docker-compose.local.yml build
# Start all services
docker compose -f docker-compose.local.yml up
# Start in background
docker compose -f docker-compose.local.yml up -d
# Build without cache (after dependency changes)
docker compose -f docker-compose.local.yml build --no-cacheDjango Startup
The local Django container runs:
python manage.py migrate
python manage.py runserver_plus 0.0.0.0:8000Celery Worker (Hot Reload)
The local Celery worker uses watchfiles for automatic restart on code changes:
watchfiles --filter python celery.__main__.main \
--args '-A config.celery_app worker -l INFO'Management Commands
# Run any Django command
docker compose -f docker-compose.local.yml run --rm django python manage.py <command>
# Examples
docker compose -f docker-compose.local.yml run --rm django python manage.py createsuperuser
docker compose -f docker-compose.local.yml run --rm django python manage.py makemigrations
docker compose -f docker-compose.local.yml run --rm django python manage.py shell_plusDatabase Access
# PostgreSQL shell
docker compose -f docker-compose.local.yml exec postgres psql -U <POSTGRES_USER> -d <POSTGRES_DB>
# Check pgvector extension
SELECT * FROM pg_extension WHERE extname = 'vector';Service URLs
| Service | URL |
|---|---|
| Django API | http://localhost:8000 |
| Flower | http://localhost:5555 |
| Mailpit | http://localhost:8025 |
Production
Build & Deploy
# Build production images
docker compose -f docker-compose.production.yml build
# Start all services
docker compose -f docker-compose.production.yml up -d
# View logs
docker compose -f docker-compose.production.yml logs -f django
docker compose -f docker-compose.production.yml logs -f celeryworkerDjango Startup (Production)
The production Django container runs:
python /app/manage.py collectstatic --noinput
gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/appStatic files are collected to S3 via django-storages.
Entrypoint
The production entrypoint waits for PostgreSQL before starting:
# Waits up to 30 seconds for PostgreSQL
# Constructs DATABASE_URL from environment variables
# Exits with error if database is unavailableTraefik (Reverse Proxy)
Traefik handles:
- HTTP → HTTPS redirect (port 80 → 443)
- Let's Encrypt SSL certificates (ACME)
- CSRF header forwarding (
X-CSRFToken) - Routing:
/*→ Django (port 5000) - Routing: Flower on port 5555
Database Backups
# Create backup
docker compose -f docker-compose.production.yml exec postgres /usr/local/bin/backup
# List backups
docker compose -f docker-compose.production.yml exec postgres /usr/local/bin/backups
# Restore from backup
docker compose -f docker-compose.production.yml exec postgres /usr/local/bin/restore <filename>
# Upload backup to S3
docker compose -f docker-compose.production.yml run --rm awscli upload
# Download backup from S3
docker compose -f docker-compose.production.yml run --rm awscli download <filename>Dockerfile Details
Multi-Stage Build
The Django Dockerfile uses a multi-stage build:
# Stage 1: Build wheels
FROM python:3.12-slim-bookworm AS python-build-stage
RUN pip install --upgrade pip
COPY requirements/ /requirements/
RUN pip wheel --wheel-dir /wheels -r /requirements/production.txt
# Stage 2: Runtime
FROM python:3.12-slim-bookworm AS python-run-stage
COPY --from=python-build-stage /wheels /wheels
RUN pip install --no-index --find-links=/wheels /wheels/*
COPY . /appBuild dependencies (installed in build stage only): cmake, g++ (needed for Docling native compilation).
Image size: ~7 GB due to Docling + PyTorch dependencies.
Security
The production image:
- Creates a non-root
djangouser - Strips development tools
- Uses minimal runtime dependencies
- Compiles translation messages during build
Environment Files
Local (.envs/.local/)
.envs/.local/.django # Django, Redis, Celery settings
.envs/.local/.postgres # PostgreSQL credentialsProduction (.envs/.production/)
.envs/.production/.django # Django, AWS, Stripe, Sentry, email
.envs/.production/.postgres # PostgreSQL credentials
.envs/.production/.traefik # Domain, email for Let's EncryptHealth Checks
# Check all services are running
docker compose -f docker-compose.local.yml ps
# Check Django is responding
curl http://localhost:8000/api/schema/
# Check database connection
docker compose exec django python manage.py check --database default
# Check Celery worker
docker compose exec django celery -A config.celery_app inspect pingTroubleshooting
| Issue | Solution |
|---|---|
| Database connection refused | Wait for PostgreSQL to be ready, check credentials |
| Celery tasks not executing | Check Redis connection, verify worker is running |
| S3 upload failing | Verify AWS credentials and bucket permissions |
| Docling build failing | Ensure Python 3.12 (not 3.13), check cmake/g++ installed |
| Out of disk space | docker system prune -a to clean unused images |
| pgvector not available | Ensure using pgvector/pgvector:pg17 image |