Self-Hosting with Docker
This guide provides a complete walkthrough for deploying the Corgi Recommender Service in a production environment using Docker Compose. The deployment includes all necessary services: PostgreSQL database, Redis cache, and the Corgi API.
Prerequisites
Before beginning deployment, ensure you have:
- Docker Engine 20.10 or later
- Docker Compose v2.0 or later
- Git for cloning the repository
- 4GB RAM minimum (8GB recommended for production)
- 10GB disk space for Docker images and data
- Domain name (optional, for HTTPS)
- SSL certificates (optional, for HTTPS)
Deployment Architecture
graph LR
subgraph External
CLIENT[Client Applications]
MASTODON[Mastodon Instances]
end
subgraph Docker["Docker Network"]
subgraph Services
API[Corgi API<br/>Port 5002]
POSTGRES[(PostgreSQL<br/>Port 5432)]
REDIS[(Redis<br/>Port 6379)]
end
end
CLIENT -->|HTTPS| API
MASTODON -->|OAuth| API
API --> POSTGRES
API --> REDIS
%% Styling
classDef service fill:#2d3748,stroke:#4299e1,stroke-width:2px,color:#e2e8f0
classDef storage fill:#2b6cb0,stroke:#63b3ed,stroke-width:2px,color:#e2e8f0
classDef external fill:#4a5568,stroke:#cbd5e0,stroke-width:2px,color:#e2e8f0
class API service
class POSTGRES,REDIS storage
class CLIENT,MASTODON external
Step 1: Repository Setup
Clone the repository and navigate to the project directory:
git clone https://github.com/your-org/corgi-recommender-service.git
cd corgi-recommender-service
Step 2: Environment Configuration
Create Production Environment File
Copy the example environment file and create your production configuration:
cp env.example .env
Configure Critical Security Settings
Security Critical
The following environment variables MUST be changed from their defaults for production deployment.
Edit .env and update these critical settings:
# SECURITY CRITICAL - Generate strong passwords
POSTGRES_PASSWORD=your-very-strong-database-password-here
API_SECRET_KEY=your-random-secret-key-minimum-32-chars
JWT_SECRET_KEY=another-random-secret-key-minimum-32-chars
USER_HASH_SALT=random-salt-for-user-hashing
# Set to production mode
CORGI_ENV=production
FLASK_ENV=production
DEBUG=false
# Configure CORS for your domains
CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
# Remove or update the Slack webhook
SLACK_WEBHOOK_URL=your-actual-slack-webhook-or-remove-this-line
Generate Secure Keys
Use these commands to generate secure random keys:
# Generate API_SECRET_KEY
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# Generate JWT_SECRET_KEY
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# Generate USER_HASH_SALT
python3 -c "import secrets; print(secrets.token_hex(16))"
Complete Production Configuration
Here's a complete example of a production-ready .env file:
# Database Configuration
POSTGRES_USER=corgi_prod
POSTGRES_PASSWORD=vErY$tr0ng!P@ssw0rd#2024
POSTGRES_DB=corgi_production
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
# Redis Configuration
REDIS_HOST=redis
REDIS_PORT=6379
# Optional: Add Redis password for additional security
# REDIS_PASSWORD=redis-password-here
# API Configuration
CORGI_API_HOST_PORT=5002
CORGI_ENV=production
FLASK_ENV=production
DEBUG=false
# Security Keys (use generated values)
API_SECRET_KEY=Kb5P-qX9mJ3nR8vT2wY6zL4fG7hA0sD1
JWT_SECRET_KEY=Nm8R-tY3wX5vB2zK9pL6jH4fA7sG0dQ1
USER_HASH_SALT=a7b9c2d4e6f8a1b3c5d7e9f0a2b4c6d8
# CORS Configuration (update with your domains)
CORS_ORIGINS=https://api.example.com,https://app.example.com
# SSL Configuration (if using HTTPS)
USE_HTTPS=true
SSL_CERT_PATH=/app/certs/cert.pem
SSL_KEY_PATH=/app/certs/key.pem
# Rate Limiting
RATE_LIMITING_ENABLED=true
RATE_LIMIT_DEFAULT=2000 per hour
RATE_LIMIT_ANONYMOUS=1000 per hour
# Monitoring (optional)
SENTRY_DSN=your-sentry-dsn-if-using-sentry
LOG_LEVEL=INFO
Step 3: SSL Certificate Setup (Optional)
If you're using HTTPS, place your SSL certificates in the certs/ directory:
mkdir -p certs
cp /path/to/your/cert.pem certs/
cp /path/to/your/key.pem certs/
chmod 600 certs/key.pem
Step 4: Deploy the Stack
Build and Start Services
Use the standalone profile for API-only deployment:
docker-compose --profile standalone up -d --build
This command will: - Build the Corgi API image with production optimizations - Start PostgreSQL with persistent storage - Start Redis with AOF persistence - Configure health checks for all services - Create an isolated Docker network
Monitor Startup Progress
Watch the logs to ensure services start correctly:
docker-compose logs -f
Look for these success indicators:
- postgres | database system is ready to accept connections
- redis | Ready to accept connections
- corgi-api | Listening at: http://0.0.0.0:5000
Step 5: Database Initialization
Run Database Migrations
After services are running, initialize the database schema:
docker-compose exec corgi-api python -m flask db upgrade
Verify Database Schema
docker-compose exec postgres psql -U corgi_prod -d corgi_production -c "\dt"
You should see tables like:
- users
- posts
- interactions
- user_embeddings
- post_embeddings
Step 6: Verification
Health Check
Verify the API is running correctly:
curl http://localhost:5002/health
Expected response:
{
"status": "healthy",
"version": "1.0.0",
"services": {
"database": "connected",
"redis": "connected"
}
}
API Endpoint Test
Test the recommendations endpoint:
curl -X GET http://localhost:5002/api/v1/recommendations \
-H "Authorization: Bearer YOUR_MASTODON_TOKEN" \
-H "X-Mastodon-Instance: mastodon.social"
Step 7: Reverse Proxy Setup (Recommended)
For production, use a reverse proxy like Nginx:
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass http://localhost:5002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts for long-running requests
proxy_read_timeout 120s;
proxy_connect_timeout 120s;
}
}
Maintenance Procedures
Viewing Logs
View logs for specific services:
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f corgi-api
# Last 100 lines
docker-compose logs --tail=100 corgi-api
Database Backup
Create automated backups of your PostgreSQL database:
# Manual backup
docker-compose exec postgres pg_dump -U corgi_prod corgi_production > backup_$(date +%Y%m%d_%H%M%S).sql
# Automated daily backups (add to crontab)
0 2 * * * cd /path/to/corgi && docker-compose exec -T postgres pg_dump -U corgi_prod corgi_production > /backups/corgi_$(date +\%Y\%m\%d).sql
Updating the Application
To update to a new version:
# Pull latest changes
git pull origin main
# Rebuild and restart services
docker-compose --profile standalone down
docker-compose --profile standalone up -d --build
# Run any new migrations
docker-compose exec corgi-api python -m flask db upgrade
Monitoring Resources
Monitor Docker resource usage:
# Container stats
docker stats
# Detailed service status
docker-compose ps
# Check service health
docker-compose exec corgi-api curl http://localhost:5000/health
Troubleshooting
Service Won't Start
Check logs for specific error messages:
docker-compose logs corgi-api | grep ERROR
Common issues:
- Database connection failed: Check POSTGRES_PASSWORD matches in .env
- Port already in use: Change CORGI_API_HOST_PORT in .env
- Permission denied: Ensure proper file permissions on SSL certificates
Database Connection Issues
Test database connectivity:
docker-compose exec corgi-api python -c "
from db.connection import get_db_connection
conn = get_db_connection()
print('Database connected successfully!')
"
Redis Connection Issues
Test Redis connectivity:
docker-compose exec redis redis-cli ping
High Memory Usage
Adjust worker processes in the Dockerfile:
# Reduce workers if memory constrained
CMD ["gunicorn", "--workers", "2", ...]
Security Checklist
Before going live, ensure:
- [ ] All default passwords changed
- [ ]
API_SECRET_KEYandJWT_SECRET_KEYare unique and strong - [ ]
USER_HASH_SALTis set - [ ]
DEBUGis set tofalse - [ ]
CORGI_ENVis set toproduction - [ ] CORS origins are properly configured
- [ ] SSL certificates are installed (if using HTTPS)
- [ ] Database backups are configured
- [ ] Monitoring is in place
- [ ] Rate limiting is enabled
- [ ] Firewall rules restrict database/Redis ports
Next Steps
After successful deployment:
- Set up monitoring: See Monitoring and Observability
- Configure backups: Implement automated backup procedures
- Set up alerts: Configure Slack or email notifications
- Load testing: Verify performance under expected load
- Security audit: Run security scanning tools
Your Corgi Recommender Service is now running in production! Monitor the logs during the first few days to ensure stable operation.