Docker Compose File Structure¶
Last Updated: February 24, 2026
Overview¶
Uplink uses Docker Compose override files to maintain clean separation between development and production configurations while sharing common base settings.
File Structure¶
uplink/
├── docker-compose.yml # Base configuration (shared)
├── docker-compose.dev.yml # Development overrides
├── docker-compose.prod.yml # Production overrides
├── docker-compose-old.yml # Backup of previous monolithic config
└── docker-compose.yml.backup # Another backup
How It Works¶
Base File (docker-compose.yml)¶
Contains shared configuration for all environments: - Service definitions (web, daphne, huey, redis, nginx, certbot) - Base ports, networks, dependencies - Health checks - No environment-specific settings
Development Overrides (docker-compose.dev.yml)¶
Extends base with development-specific settings:
- Volume mounts (- .:/app) for code hot-reloading
- DATABASE_HOST=host.docker.internal (connects to host MySQL on port 3307)
- REDIS_HOST=redis (uses Docker Redis container)
- DEBUG=True for daphne and huey
- restart: unless-stopped (don't auto-restart during development)
- gunicorn --reload flag
Production Overrides (docker-compose.prod.yml)¶
Extends base with production-specific settings: - NO volume mounts (code baked into image) - DATABASE_HOST=${DATABASE_HOST} (uses DigitalOcean MySQL from .env) - REDIS_HOST=redis (uses Docker Redis container) - DEBUG=False for all services - restart: always (auto-restart on failure) - gunicorn production settings
Usage¶
Local Development¶
# Manually specify both files
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# Or use deploy.sh (auto-detects environment)
./deploy.sh docker-up
Production¶
# Manually specify both files
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Or use deploy.sh (auto-detects environment)
./deploy.sh deploy-full
Environment Detection¶
The deploy.sh script automatically detects your environment:
# Checks for:
1. /srv/uplink/app/.production file
2. hostname = "uplink"
# If either exists → production (uses docker-compose.prod.yml)
# Otherwise → development (uses docker-compose.dev.yml)
Key Differences¶
| Aspect | Development | Production |
|---|---|---|
| Compose Files | base + dev |
base + prod |
| Code Reloading | Yes (volume mounted) | No (baked into image) |
| Database | Host MySQL (port 3307) | DigitalOcean MySQL |
| DEBUG | Mixed (False for web, True for daphne/huey) | False (all services) |
| Restart Policy | unless-stopped | always |
| Gunicorn | --reload flag | Production optimized |
| Direct Access | localhost:8001 (web), localhost:9000 (daphne) | nginx proxy (80/443) |
Benefits¶
✅ No .env changes needed - Same .env works for both pipenv and Docker ✅ Clear separation - Dev and prod settings don't interfere ✅ Shared base - Common config in one place (DRY principle) ✅ Automatic detection - deploy.sh uses right files for environment ✅ Standard practice - Follows Docker Compose best practices
Transitioning from Old Setup¶
Old way: Single docker-compose.yml with environment variables toggling behavior
New way: - Base config + environment-specific overrides - Clear separation of concerns - Auto-detection of environment
Compatibility:
- Can still run pipenv locally (pipenv run honcho start)
- Can run Docker locally (./deploy.sh docker-up)
- Both use same database (your local MySQL)
- Both work simultaneously (different ports)
Common Commands¶
# Development
./deploy.sh docker-up # Start dev containers
./deploy.sh docker-down # Stop dev containers
./deploy.sh docker-restart # Restart dev containers
./deploy.sh docker-logs # View dev logs
# Production (on production server)
./deploy.sh deploy-full # Full deployment (recommended)
./deploy.sh deploy-quick # Quick code-only deployment
./deploy.sh deploy-rebuild # Complete rebuild
./deploy.sh status # Check status
./deploy.sh logs # View logs
Migration Notes¶
For Existing Production Server¶
-
Create production marker file:
-
Deploy script will automatically use production compose files
-
No other changes needed!
For Local Development¶
-
No changes needed - works automatically
-
deploy.sh detects you're NOT on production server
-
Uses dev compose files automatically
Troubleshooting¶
Issue: "Service 'web' is not running"
# Check which files are being used
docker compose -f docker-compose.yml -f docker-compose.dev.yml ps
# Or check environment detection
./deploy.sh status
Issue: "Database connection failed"
# Development: Check host MySQL is running
sudo service mysql status
# Production: Check .env has correct DigitalOcean credentials
grep DATABASE_HOST .env
Issue: "Code changes not reflecting"
# Development: Volume should be mounted
docker compose -f docker-compose.yml -f docker-compose.dev.yml exec web ls -la /app
# Production: Code baked into image, need to rebuild
./deploy.sh deploy-full