compose.yaml runs the marketing site and the API. It does not run the studio, portfolio, docs or blog, and it has no PostgreSQL container.
| Service | What it is | Port |
|---|---|---|
web |
The marketing site (apps/site), built from the root Dockerfile as a Next.js standalone app |
127.0.0.1:3000 |
api |
The Express API, built from apps/server/Dockerfile |
127.0.0.1:8080 |
migrate |
Runs prisma migrate deploy once, before api starts |
none |
redis |
Redis 7 with a password and a memory limit | none |
redisinsight |
Redis browser, only with --profile dev |
127.0.0.1:5540 |
Ports bind to 127.0.0.1 only. Put nginx (or another reverse proxy) on the host in front of them.
-
Create the env file compose reads, and fill it in:
cp .env.docker.example .env.docker
You need your own PostgreSQL, for example Neon. Set
DATABASE_URLto it. -
Build and start:
docker compose --env-file .env.docker up -d --build
Compose refuses to start while a required variable is empty and names it. compose.yaml marks each one with ${VAR:?}. Some required variables, such as TRUST_PROXY, WEB_CONCURRENCY and REDIS_PASSWORD, are not in .env.docker.example yet; add them yourself. The API then checks formats at boot (apps/server/src/config/environmentSchema.ts).
NEXT_PUBLIC_* values are built into the site image. After changing one, rebuild with docker compose --env-file .env.docker build web.
- API variables and production rules:
apps/server/.env.exampleandapps/server/README.md. - Studio deploy (pm2 + nginx, no Docker):
apps/studio/README.md. - Proxy and TLS setup: Docker deployment guide.