Local Deployment
Docker-based local development infrastructure and setup.
Local Deployment
ByteBite local development runs entirely in Docker with Traefik for hostname-based routing. No Dokploy or TLS is involved.
Prerequisites
- macOS (primary target) or Linux
- Docker Desktop or compatible runtime (Compose v2+)
- Git, pnpm, Node.js 24 LTS (for host-side lint/typecheck/build)
/etc/hostsentries (see below)
Architecture
Browser -> Traefik :80 (compose.yml)
-> file provider (infrastructure/traefik/dev/dynamic.yml)
-> storefront | dashboard | api | docs
-> PostgreSQL (backend network)
-> MinIO (backend network, API only)Traefik uses the file provider only — Docker provider is disabled for OrbStack compatibility. Service traefik.* labels in compose.yml are documentation only.
See Network for Docker network details and Architecture for request flows.
Compose files
| File | Purpose |
|---|---|
compose.yml | Base services, networks, Traefik, PostgreSQL, MinIO |
compose.dev.yml | Dev overrides: bind mounts, hot reload commands |
Start with:
pnpm dev # docker compose -f compose.yml -f compose.dev.yml upLocal hostnames
Domain suffix: .bytebite.test
| Host | Service | Port (internal) |
|---|---|---|
storefront.bytebite.test | Storefront (neutral dev host) | 3000 |
dashboard.bytebite.test | Dashboard (Vite dev) | 5173 |
api.bytebite.test | API (direct) | 3001 |
docs.bytebite.test | Docs | 3002 |
luigi.bytebite.test | Storefront (seeded tenant) | 3000 |
mario.bytebite.test | Storefront (seeded tenant) | 3000 |
unknown.bytebite.test | Storefront (unknown tenant test) | 3000 |
No wildcard DNS — each host must be listed in /etc/hosts.
/etc/hosts — IPv4 and IPv6 required
macOS clients may attempt AAAA (IPv6) lookups for .test hostnames. If only 127.0.0.1 entries exist, requests can hang for ~5 seconds before falling back to IPv4.
Add both 127.0.0.1 and ::1 for every host:
127.0.0.1 storefront.bytebite.test
127.0.0.1 dashboard.bytebite.test
127.0.0.1 api.bytebite.test
127.0.0.1 docs.bytebite.test
127.0.0.1 luigi.bytebite.test
127.0.0.1 mario.bytebite.test
127.0.0.1 unknown.bytebite.test
::1 storefront.bytebite.test
::1 dashboard.bytebite.test
::1 api.bytebite.test
::1 docs.bytebite.test
::1 luigi.bytebite.test
::1 mario.bytebite.test
::1 unknown.bytebite.testSee root README.md for a convenient macOS one-liner.
Same-origin /api routing
Browsers call /api/* on the same host as the UI. Traefik strips the /api prefix before forwarding to Fastify:
http://luigi.bytebite.test/api/health
-> Traefik (strip-api-prefix middleware)
-> api:3001 /healthConfigured in infrastructure/traefik/dev/dynamic.yml. No CORS layer is needed for the normal browser path.
API_INTERNAL_URL
Storefront SSR uses API_INTERNAL_URL=http://api:3001 (set in compose.yml). Server-side fetches send X-ByteBite-Tenant-Host with the original browser hostname. See Architecture.
PostgreSQL and MinIO
| Service | Access |
|---|---|
| PostgreSQL | 127.0.0.1:5432 (host-published for tooling) |
| MinIO console | http://localhost:9001 |
| Traefik dashboard | http://localhost:8080 |
| Drizzle Studio | http://localhost:4983 (pnpm db:studio) |
Inside the API container, Compose overrides DATABASE_URL to postgres://...@postgres:5432/... and S3_ENDPOINT to http://minio:9000.
Migrations and seeds
The API does not auto-migrate. With the stack running:
pnpm db:migrate
pnpm db:seedLocal seeds create luigi.bytebite.test and mario.bytebite.test. Do not run pnpm db:seed:staging locally — it writes staging hostnames.
Smoke tests
curl -s "http://api.bytebite.test/health"
curl -s "http://luigi.bytebite.test/api/health"
curl -s "http://luigi.bytebite.test/api/storefront/restaurant"
curl -s "http://unknown.bytebite.test/api/storefront/restaurant" -o /dev/null -w "%{http_code}"More checks: Validation.
Testing deployment compose locally
Use a separate project name to avoid replacing dev containers:
docker compose -p bytebite-staging -f compose.deploy.yml up --buildThis does not include Traefik, PostgreSQL, or local routing.
Troubleshooting
| Issue | Fix |
|---|---|
| ~5s request delay on macOS | Add ::1 entries to /etc/hosts |
api.bytebite.test connection refused | Ensure pnpm dev is running |
| New docs page not visible | Restart docs service after adding MDX files |
| Host-side build corrupts Next dev cache | Anonymous volumes protect .next — avoid host pnpm build for storefront/docs during dev |
See Troubleshooting for infrastructure issues.
Related
- Getting started — first-time monorepo setup
- Environments — local vs staging comparison
- ADR-012 Local development
- ADR-013 Local domains