Docker Compose Deployment with Traefik


This guide walks you through deploying a scalable Django app with Traefik, PostgreSQL, Redis, Celery, and automated data loadingโ€”optimized for modern cloud and VPS environments.

Service Overview:

  • traefik: Reverse proxy and SSL termination for secure, scalable routing.
  • db: PostgreSQL database for persistent storage.
  • redis: In-memory cache and message broker for fast data and background tasks.
  • migrate: One-off job to run Django migrations, collect static files, and load initial data.
  • api: Main Django application (Django REST Framework is used for the API), served by Gunicorn, auto-scaled and load-balanced.
  • celery_worker: Background task processing with Celery.
  • celery_beat: Scheduled task runner for periodic jobs.

๐Ÿš€ Quick Start

  1. Start all services (development or production):
   docker compose up --build
  1. Stop all services:
   docker compose down
  1. Check service health:
   docker compose ps
  1. View logs:
   docker compose logs -f

๐Ÿ—๏ธ Architecture

Services

  • Traefik: Reverse proxy with automatic SSL, load balancing, and service discovery
  • API (Django + DRF): Scalable Django application (3 replicas by default)
  • Database (PostgreSQL): Persistent data storage
  • Redis: Caching and session storage

Network Flow

Internet โ†’ Traefik (80/443) โ†’ Django API (Load Balanced)

๐ŸŒ Access Points

Development

  • API: http://localhost
  • Traefik Dashboard: http://traefik.localhost:8080
  • Database: localhost:5432
  • Redis: localhost:6379

Production

  • API: https://yourdomain.com
  • Traefik Dashboard: https://traefik.yourdomain.com:8080

โš™๏ธ Environment Variables

Create a .env file with the following variables:

# Database Configuration
POSTGRES_DB=my_ug_online
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres123
DB_HOST=db
DB_PORT=5432

# Django Configuration
DJANGO_SECRET_KEY=your-super-secret-key-change-this-in-production
DJANGO_DEBUG=False
ALLOWED_HOSTS=localhost,127.0.0.1

# Environment
ENVIRONMENT=production

# Traefik Configuration
DOMAIN=yourdomain.com
ACME_EMAIL=admin@yourdomain.com

# Redis Configuration
REDIS_URL=redis://redis:6379/0

๐Ÿ› ๏ธ Common Docker Compose Commands

# Start all services (build if needed)
docker compose up --build

# Stop all services
docker compose down

# View logs
docker compose logs -f

# Check service status
docker compose ps

# Access Django shell
docker compose exec api python manage.py shell

# Run migrations
docker compose exec api python manage.py migrate

# Create superuser
docker compose exec api python manage.py createsuperuser

# Feed data from assets
docker compose exec api python feed_data.py

# Check database health
docker compose exec db pg_isready -U postgres

# Check Redis
docker compose exec redis redis-cli ping

๐Ÿ”ง Configuration

Traefik Features

  • Automatic SSL: Let’s Encrypt certificates
  • Load Balancing: Round-robin across API replicas
  • Dashboard: Web UI for monitoring
  • Middleware: Redirect HTTP to HTTPS

Scaling Configuration

deploy:
  replicas: 3  # Number of API instances
  resources:
    limits:
      memory: 1G
      cpus: '0.5'
    reservations:
      memory: 512M
      cpus: '0.25'

Production Features

  • SSL/TLS: Automatic certificate management
  • Security Headers: XSS protection, CSRF, etc.
  • Caching: Redis for sessions and cache

๐Ÿ“Š Monitoring

Traefik Dashboard

  • URL: http://traefik.localhost:8080 (dev) or https://traefik.yourdomain.com:8080 (prod)
  • Features: Service status, request metrics, SSL certificates

๐Ÿ”’ Security

Production Checklist

  • [ ] Change default passwords in .env
  • [ ] Set valid DOMAIN and ACME_EMAIL
  • [ ] Configure firewall rules
  • [ ] Set up monitoring and alerting (if needed)

SSL Configuration

  • Automatic: Let’s Encrypt certificates
  • Manual: Place certificates in ./certs/
  • Renewal: Automatic via Traefik

๐Ÿž Troubleshooting & Common Errors

1. Bad Gateway (Traefik)

Symptom: Traefik dashboard shows routes, but accessing the site gives a Bad Gateway error.

Solution:

  • Ensure Gunicorn is binding to 0.0.0.0:8000 (not 127.0.0.1:8000).
  • In docker-compose.yml, use a single-line command for Gunicorn:
  command: >
    sh -c "exec gunicorn core.wsgi:application --bind 0.0.0.0:8000 ..."
  • Do not use backslashes (\) for line continuation in YAML commands.
  • Rebuild and restart your containers after changes.

2. CSRF Verification Failed (403)

Symptom: You see “CSRF verification failed. Request aborted.” when submitting forms or making API requests.

Solution:

  • Add your domain(s) to CSRF_TRUSTED_ORIGINS in core/settings.py:
  CSRF_TRUSTED_ORIGINS = [
      'https://myug-online.eventsgalleryug.com',
      'http://myug-online.eventsgalleryug.com',
      'http://localhost',
      'http://127.0.0.1',
  ]
  • Restart your containers after updating settings.

3. Superuser Cannot Log In to Admin

Symptom: “Please enter the correct username and password for a staff account.”

Solution:

  • Ensure the superuser is created with is_staff=True.
  • The feed_data.py script now sets is_staff=True for the superuser.
  • If you use environment variables to create a superuser, ensure is_staff is set in your user model or update the user after creation.

4. Data Not Loaded for Ministry Workers or Judiciary Members Without District/Ministry

Symptom: Some ministry workers or judiciary members are missing if not tied to a district or ministry.

Solution:

  • The feed_data.py script has been updated to load all ministry workers and judiciary members, even if not tied to a district or ministry (sets the field to None).
  • Rebuild and redeploy your containers to use the updated script.

5. Docker Image Architecture Issues (Apple Silicon, ARM64)

Symptom: Error: “no matching manifest for linux/arm64/v8 in the manifest list entries”

Solution:

  • Build and push multi-architecture images using Docker Buildx:
  docker buildx build --platform linux/amd64,linux/arm64 -t yourusername/yourimage:latest --push .
  • Update your deployment to use the new image.

๐Ÿš€ Deploying to a VPS (with SCP & Docker Hub Private Repos)

1. Copy Project Files to VPS Using SCP

If you need to transfer files (such as your .env or deployment scripts) to your VPS:

scp -r /local/project/path username@your-vps-ip:/remote/project/path
  • Replace /local/project/path with your local directory.
  • Replace username@your-vps-ip:/remote/project/path with your VPS user, IP, and target directory.

2. Using Docker Hub Private Repositories

If your Docker image is stored in a private Docker Hub repo:

  1. Login to Docker Hub on the VPS:
   docker login

Enter your Docker Hub username and password (or access token).

  1. Pull the Private Image:
   docker pull yourusername/yourimage:latest
  1. Run or Deploy with Docker Compose:
  • Make sure your docker-compose.yml references the private image tag.
  • Start your services:
    sh docker compose up -d

3. Tips for Secure Deployment

  • Never commit secrets or .env files to version control.
  • Use SSH keys for scp/ssh access.
  • Use Docker secrets or environment variables for sensitive data in production.

๐Ÿง Docker & Compose Setup on Ubuntu 24 (VPS)

1. Create a New User (Recommended)

Before installing Docker, create a new user for deployment (do not use root):

sudo adduser deployuser
sudo usermod -aG sudo deployuser
su - deployuser

Replace deployuser with your preferred username.

2. Install Docker & Compose (Convenience Script)

Ubuntu 24 may come with Docker but often lacks Docker Compose or has an outdated version. The recommended way is to use Docker’s official convenience script:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh ./get-docker.sh
  • This installs the latest Docker and Docker Compose plugin.
  • You can check versions with:
  docker --version
  docker compose version

3. Add Your User to the Docker Group

To run Docker without sudo:

sudo usermod -aG docker $USER
newgrp docker
  • Log out and back in, or run newgrp docker for the group change to take effect.

4. Troubleshooting

  • If you see docker: command not found or docker compose: command not found, ensure you used the convenience script and your user is in the docker group.
  • If you get permission errors, double-check your group membership.


Leave a Reply

Your email address will not be published. Required fields are marked *