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
- Start all services (development or production):
docker compose up --build
- Stop all services:
docker compose down
- Check service health:
docker compose ps
- 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
andACME_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
(not127.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
incore/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 setsis_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 toNone
). - 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:
- Login to Docker Hub on the VPS:
docker login
Enter your Docker Hub username and password (or access token).
- Pull the Private Image:
docker pull yourusername/yourimage:latest
- 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
ordocker compose: command not found
, ensure you used the convenience script and your user is in thedocker
group. - If you get permission errors, double-check your group membership.
Leave a Reply