Docker Compose Deployment
This guide explains how to run Cascadia PLM using Docker and Docker Compose.
Prerequisites
- Docker Engine 20.10 or later
- Docker Compose V2 (comes with Docker Desktop)
- At least 2GB of available RAM
- 5GB of available disk space
Quick Start
-
Copy the Docker environment file:
cp .env.docker .env -
Edit the
.envfile and update the following critical values:SESSION_SECRET: Generate a secure random 32-character stringPOSTGRES_PASSWORD: Change from default for productionPGADMIN_PASSWORD: Change from default if using pgAdmin
-
Start the application:
docker-compose up -d -
Access the application:
- Application: http://localhost:3000
- pgAdmin (optional): http://localhost:5050
-
View logs:
docker-compose logs -f app
Architecture
The Docker setup includes five services:
1. PostgreSQL Database (postgres)
- Image:
postgres:18-alpine - Port: 5432 (configurable via
POSTGRES_PORT) - Data: Persisted in
postgres_datavolume - Health Check: Automatic readiness probe
2. Cascadia Application (app)
- Build: Multi-stage Dockerfile (builder + production)
- Port: 3000 (configurable via
APP_PORT) - Storage: Persistent volumes for files and vault
- Auto-migration: Runs
drizzle-kit pushon startup
3. RabbitMQ (rabbitmq)
- Image:
rabbitmq:3-management-alpine - Ports: 5672 (AMQP), 15672 (Management UI)
- Data: Persisted in
rabbitmq_datavolume - Purpose: Message queue for background job processing
- Health Check: Automatic ping probe
4. Jobs Worker (jobs-worker-dev)
- Profile:
dev(for development with live reload) - Purpose: Processes background jobs from RabbitMQ queue
- Features: Workflow notifications, async processing
- Mounts: Source code for live reload during development
5. pgAdmin (Optional, pgadmin)
- Profile:
tools(not started by default) - Port: 5050 (configurable via
PGADMIN_PORT) - Purpose: Web-based PostgreSQL administration
Configuration
Environment Variables
All configuration is done through the .env file. Key variables:
| Variable | Default | Description |
|---|---|---|
APP_PORT | 3000 | Application port on host |
POSTGRES_DB | cascadia | Database name |
POSTGRES_USER | postgres | Database user |
POSTGRES_PASSWORD | postgres | Database password (change in production!) |
POSTGRES_PORT | 5432 | PostgreSQL port on host |
SESSION_SECRET | (required) | Secure random string for sessions |
NODE_ENV | production | Node.js environment |
RABBITMQ_USER | cascadia | RabbitMQ username |
RABBITMQ_PASSWORD | cascadia | RabbitMQ password (change in production!) |
RABBITMQ_PORT | 5672 | RabbitMQ AMQP port on host |
RABBITMQ_MGMT_PORT | 15672 | RabbitMQ Management UI port |
WORKER_CONCURRENCY | 5 | Number of concurrent job workers |
Docker Compose Commands
Start Services
# Start in detached mode (app, postgres, rabbitmq)
docker-compose up -d
# Start with development jobs worker (for background job processing)
docker-compose --profile dev up -d
# Start with pgAdmin tool
docker-compose --profile tools up -d
# Start all services (app, jobs worker, pgAdmin)
docker-compose --profile dev --profile tools up -d
# Start and rebuild images
docker-compose up -d --build
Stop Services
# Stop containers
docker-compose stop
# Stop and remove containers
docker-compose down
# Stop and remove containers + volumes (deletes data!)
docker-compose down -v
View Logs
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f app
docker-compose logs -f postgres
docker-compose logs -f rabbitmq
docker-compose logs -f jobs-worker-dev
# Last 100 lines
docker-compose logs --tail=100 app
Execute Commands
# Access app container shell
docker-compose exec app sh
# Run database migrations
docker-compose exec app npx drizzle-kit push
# Access PostgreSQL CLI
docker-compose exec postgres psql -U postgres -d cascadia
Database Management
Backup Database
docker-compose exec postgres pg_dump -U postgres cascadia > backup.sql
Restore Database
cat backup.sql | docker-compose exec -T postgres psql -U postgres -d cascadia
Access Database with psql
docker-compose exec postgres psql -U postgres -d cascadia
Use pgAdmin
- Start with tools profile:
docker-compose --profile tools up -d - Open http://localhost:5050
- Login with credentials from
.env - Add server:
- Name: Cascadia
- Host:
postgres - Port: 5432
- Database:
cascadia - Username:
postgres - Password: (from
POSTGRES_PASSWORD)
Use RabbitMQ Management UI
- Open http://localhost:15672
- Login with credentials from
.env(default:cascadia/cascadia) - Monitor queues, connections, and message rates
- View job queue status under Queues tab
Production Deployment
Security Checklist
Before deploying to production:
- Change
POSTGRES_PASSWORDto a strong password - Generate a secure
SESSION_SECRET(32+ random characters) - Change
RABBITMQ_PASSWORDto a strong password - Change
PGADMIN_PASSWORDif using pgAdmin - Set
NODE_ENV=production - Configure proper
BASE_URLfor your domain - Enable HTTPS/TLS (use reverse proxy like Nginx or Traefik)
- Set up automated backups
- Configure firewall rules (only expose necessary ports)
- Do not expose RabbitMQ management port (15672) externally
- Review and configure OAuth providers if needed
- Set up monitoring and alerting
Recommended Production Setup
- Use Docker Secrets for sensitive data
- Use a reverse proxy (Nginx, Traefik, Caddy) for HTTPS/TLS termination
- Enable resource limits in
docker-compose.yml - Configure proper logging (JSON logs to stdout)
Volumes
The setup creates persistent volumes:
| Volume | Purpose |
|---|---|
postgres_data | PostgreSQL database files |
app_storage | Uploaded files and attachments |
app_vault | Secure document storage |
rabbitmq_data | RabbitMQ message queue data |
pgadmin_data | pgAdmin configuration |
Backup Volumes
# Backup app storage
docker run --rm -v cascadiaapp_app_storage:/data -v $(pwd):/backup alpine tar czf /backup/storage-backup.tar.gz -C /data .
# Restore app storage
docker run --rm -v cascadiaapp_app_storage:/data -v $(pwd):/backup alpine tar xzf /backup/storage-backup.tar.gz -C /data
Troubleshooting
Application won't start
- Check logs:
docker-compose logs app - Verify database is healthy:
docker-compose ps - Check environment variables:
docker-compose config
Database connection errors
- Ensure
DATABASE_URLpoints topostgres(container name), notlocalhost - Verify
POSTGRES_PASSWORDmatches between services - Check if PostgreSQL is healthy:
docker-compose ps postgres
Port conflicts
If ports 3000 or 5432 are already in use:
-
Edit
.envfile:APP_PORT=3001POSTGRES_PORT=5433 -
Restart services:
docker-compose downdocker-compose up -d
RabbitMQ connection errors
- Ensure RabbitMQ is healthy:
docker-compose ps rabbitmq - Verify credentials match between app and rabbitmq containers
- Check RabbitMQ logs:
docker-compose logs rabbitmq - Wait for RabbitMQ to fully initialize (health check takes ~30s)
Jobs not processing
- Ensure jobs worker is running:
docker-compose --profile dev ps - Check worker logs:
docker-compose logs jobs-worker-dev - Verify RabbitMQ connection in worker logs
- Check job queue in RabbitMQ Management UI (http://localhost:15672)
Rebuild from scratch
# Stop and remove everything
docker-compose down -v
# Remove built images
docker-compose build --no-cache
# Start fresh
docker-compose up -d