Overview
This guide covers running Comp with Docker Compose. The stack includes:| Service | Purpose | Port |
|---|---|---|
migrator | Runs Prisma migrations against your database | - |
seeder | Loads reference data (frameworks, controls) | - |
app | Main Comp application | 3000 |
portal | Customer trust portal | 3002 |
Prerequisites
- Docker Desktop or Docker Engine installed
- External PostgreSQL 14+ with SSL (e.g., Neon, DigitalOcean, RDS)
- Resend account for transactional email
- Trigger.dev account for background workflows
Environment File Layout
| File | Services |
|---|---|
packages/db/.env | migrator, seeder |
apps/app/.env | app |
apps/portal/.env | portal |
env_file: in docker-compose.yml.
Minimal Required Environment
For a functional Docker deployment, you need:packages/db/.env
packages/db/.env
apps/app/.env
apps/app/.env
apps/portal/.env
apps/portal/.env
Build-Time vs Runtime Variables
| Phase | Variables | How They’re Set |
|---|---|---|
| Build-time | NEXT_PUBLIC_* | Docker build args in docker-compose.yml |
| Runtime | Everything else | Service env files (.env) |
NEXT_PUBLIC_BETTER_AUTH_URLNEXT_PUBLIC_PORTAL_URLNEXT_PUBLIC_POSTHOG_KEYNEXT_PUBLIC_POSTHOG_HOSTNEXT_PUBLIC_IS_DUB_ENABLEDNEXT_PUBLIC_GTM_IDNEXT_PUBLIC_LINKEDIN_PARTNER_IDNEXT_PUBLIC_LINKEDIN_CONVERSION_IDNEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABELNEXT_PUBLIC_API_URL
NEXT_PUBLIC_BETTER_AUTH_URL is used at build time.
docker-compose.yml passes build args from shell environment variables (e.g., ${BETTER_AUTH_URL}). Export these before running docker compose build, or set them inline.Build & Run
1. Prepare Environment Files
2. Export Build Args
Export the build-time variables needed bydocker-compose.yml:
3. Build Images
4. Run Migrations & Seed
migrator runs
seeder upserts reference data (frameworks, controls) — idempotent.
prisma migrate deploy — safe to run repeatedly.seeder upserts reference data (frameworks, controls) — idempotent.
5. Start Services
6. Verify Health
Deploy Trigger.dev Tasks
Trigger.dev runs as a hosted service. Deploy your tasks from your workstation:TRIGGER_SECRET_KEY in apps/app/.env from your Trigger.dev project settings.
Fresh Install (Optional Clean)
To remove all images and volumes for a clean rebuild:Logging
Docker Compose is configured with log rotation to prevent disk exhaustion. All services use thejson-file driver with these defaults:
| Setting | Value | Description |
|---|---|---|
max-size | 10m | Rotate logs at 10 MB |
max-file | 5 | Keep up to 5 rotated files (~50 MB per service) |
compress | true | Compress rotated files |
Viewing Logs
Custom Log Configuration
To adjust logging for a specific service (e.g., ifapp is particularly chatty), create a docker-compose.override.yml:
For centralized logging (ELK, Loki, Splunk), you can switch the logging driver to
fluentd, gelf, or loki. See Docker’s logging driver documentation.Production Tips
HTTPS & Domains
Place a reverse proxy (nginx, Caddy, Traefik) in front. Update
BETTER_AUTH_URL and NEXT_PUBLIC_BETTER_AUTH_URL to your public HTTPS domains.Strong Secrets
Generate secrets with
openssl rand -base64 32. Rotate periodically.Database Security
Require SSL. Restrict network access via VPC, IP allowlist, or private networking.
Disk Monitoring
Monitor
/var/lib/docker disk usage. Periodically prune unused containers and images.Troubleshooting
Builds succeed but containers crash at startup
The Dockerfile setsSKIP_ENV_VALIDATION=true at build time, so missing env vars are only caught at runtime.
Check logs to identify missing variables:
process.env.* or “Missing env var”, then compare with the Environment Reference.
Common Misconfigurations
| Issue | Solution |
|---|---|
Using root .env | Docker reads per-service env files only |
Missing DATABASE_URL | Must be set in all three env files |
Missing TRIGGER_SECRET_KEY | Required in apps/app/.env for workflows |
| Mismatched auth URLs | Ensure BETTER_AUTH_URL matches NEXT_PUBLIC_BETTER_AUTH_URL |
| Build args not exported | Export BETTER_AUTH_URL and BETTER_AUTH_URL_PORTAL before build |
Container won’t start
Database connection fails
- Verify
DATABASE_URLformat:postgresql://user:pass@host:5432/db?sslmode=require - Ensure your IP is allowlisted in the database firewall
- Test connectivity:
docker compose run --rm app sh -c "nc -zv <db-host> 5432"

