Complete guide for deploying Payego using Docker and Docker Compose
Payego's Docker setup includes:
- Backend API (Rust/Axum) with automatic migrations
- PostgreSQL Database with persistent storage
- Prometheus for metrics collection
- Grafana for metrics visualization
- Docker 20.10+
- Docker Compose 2.0+
.envfile configured (see below)
Copy the example environment file and configure it:
cp .env.example .envRequired environment variables:
# Database Configuration
DB_USER=postgres
DB_PASSWORD=your_secure_password_here
DB_NAME=payego
DB_PORT=5432
# Application Port
APP_PORT=8080
# JWT Configuration
JWT_SECRET=your_super_secret_key_must_be_at_least_32_characters_long
JWT_EXPIRATION_HOURS=2
ISSUER=payego-api
AUDIENCE=payego-client
# Payment Providers
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
PAYSTACK_SECRET_KEY=sk_test_...
PAYSTACK_WEBHOOK_SECRET=whsec_...
PAYPAL_CLIENT_ID=...
PAYPAL_SECRET=...
# Application Settings
RUST_LOG=info
CORS_ORIGINS=http://localhost:5173,http://localhost:3000Start all services:
docker-compose up --build -dThe -d flag runs containers in detached mode (background).
Check that all services are running:
docker-compose psYou should see 4 services running:
payego-app-1(Backend API)payego-db-1(PostgreSQL)payego-prometheus-1(Metrics)payego-grafana-1(Dashboards)
Once deployed, access the services at:
| Service | URL | Description |
|---|---|---|
| Backend API | http://localhost:8080 | Main application API |
| Swagger UI | http://localhost:8080/swagger-ui/ | API documentation |
| Database | localhost:5432 | PostgreSQL (use DB client) |
| Prometheus | http://localhost:9090 | Metrics collection |
| Grafana | http://localhost:3000 | Metrics dashboards (admin/admin) |
The Dockerfile uses a multi-stage build for optimal image size:
-
Builder Stage (
rust:1.81-slim-bullseye):- Installs build dependencies
- Compiles Diesel CLI
- Builds Rust application in release mode
- Uses dependency caching for faster rebuilds
-
Runtime Stage (
debian:bullseye-slim):- Minimal runtime dependencies
- Non-privileged user (
appuser) - Automatic database migrations on startup
- ~200MB final image size
When the container starts:
- Wait for Database: Checks PostgreSQL readiness
- Run Migrations: Applies all pending Diesel migrations
- Start Application: Launches Payego API server
ports:
- "8080:8080" # API server
environment:
- DATABASE_URL=postgres://user:pass@db:5432/payego
- JWT_SECRET=...
- STRIPE_SECRET_KEY=...
# ... other env vars
depends_on:
- dbKey Features:
- Automatic database migrations
- Health checks via
pg_isready - Restart policy:
always - Custom DNS (8.8.8.8, 8.8.4.4)
image: postgres:15-alpine
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/dataKey Features:
- PostgreSQL 15 Alpine (lightweight)
- Persistent volume for data
- Automatic initialization
Prometheus:
- Collects metrics from Payego API
- Configuration:
prometheus.yml - Port: 9090
Grafana:
- Visualizes Prometheus metrics
- Default credentials:
admin/admin - Port: 3000
All services:
docker-compose logs -fSpecific service:
docker-compose logs -f app
docker-compose logs -f dbLast 100 lines:
docker-compose logs --tail=100 appAll services:
docker-compose restartSpecific service:
docker-compose restart appdocker-compose downStop and remove volumes (
docker-compose down -vConnect to PostgreSQL:
docker-compose exec db psql -U postgres -d payegoRun SQL query:
docker-compose exec db psql -U postgres -d payego -c "SELECT * FROM users LIMIT 5;"If you need to run migrations without restarting:
docker-compose exec app diesel migration rundocker-compose exec app /bin/shCheck logs:
docker-compose logs appCommon issues:
- Missing environment variables → Check
.envfile - Database not ready → Wait for
dbservice to be healthy - Port already in use → Change
APP_PORTin.env
Verify database is running:
docker-compose ps dbCheck database logs:
docker-compose logs dbTest connection:
docker-compose exec app pg_isready -h db -p 5432View migration status:
docker-compose exec app diesel migration listRevert last migration:
docker-compose exec app diesel migration revertReset database (
docker-compose down -v
docker-compose up -dCheck application logs:
docker-compose logs --tail=200 appCommon causes:
- Invalid JWT_SECRET (must be 32+ characters)
- Missing payment provider credentials
- Database schema mismatch
If port 8080 is already in use, change it in .env:
APP_PORT=8081Then restart:
docker-compose down
docker-compose up -dFor production, ensure you:
- Use strong, unique passwords
- Set
RUST_LOG=warnorerror(notdebug) - Configure proper
CORS_ORIGINS - Use production payment provider keys
- Set secure
JWT_SECRET(32+ random characters)
Database:
- Change default PostgreSQL password
- Restrict database port exposure (remove from
portsif not needed externally) - Use encrypted connections
Application:
- Run behind reverse proxy (nginx/Traefik)
- Enable HTTPS/TLS
- Configure rate limiting
- Set up firewall rules
Horizontal scaling:
docker-compose up -d --scale app=3Note: Requires load balancer configuration.
Create backup:
docker-compose exec db pg_dump -U postgres payego > backup.sqlRestore backup:
cat backup.sql | docker-compose exec -T db psql -U postgres payegoIf deploying to cloud with different CPU architecture (e.g., Mac M1 → AMD64 cloud):
docker build --platform=linux/amd64 -t payego:latest .Tag image:
docker tag payego:latest your-registry.com/payego:latestPush to registry:
docker push your-registry.com/payego:latest- Push image to Amazon ECR
- Create task definition with environment variables
- Configure RDS PostgreSQL instance
- Set up Application Load Balancer
- Deploy ECS service
- Push image to Google Container Registry
- Create Cloud SQL PostgreSQL instance
- Deploy with environment variables
- Configure Cloud Run service
Access Prometheus at http://localhost:9090
Available metrics:
- HTTP request duration
- Request count by endpoint
- Database connection pool stats
- System resource usage
Access Grafana at http://localhost:3000
Default credentials: admin/admin
Setup:
- Add Prometheus data source (http://prometheus:9090)
- Import dashboards from
grafana/provisioning/ - Create custom dashboards as needed
- Pull latest code
- Rebuild and restart:
git pull
docker-compose up --build -dRebuild with no cache:
docker-compose build --no-cache
docker-compose up -dRemove unused images:
docker image prune -aRemove unused volumes:
docker volume prune- Development: Use
docker-compose up(without-d) to see logs in real-time - Production: Always use
-dflag and monitor logs separately - Debugging: Use
docker-compose exec app /bin/shto inspect container - Performance: Monitor Grafana dashboards for bottlenecks
- Backups: Schedule regular database backups in production
If you encounter issues:
- Check logs:
docker-compose logs app - Verify environment variables in
.env - Ensure all required services are running
- Check main README for application-specific details
- Review Swagger UI for API documentation