Botanica/docs/DEPLOYMENT.md

3.5 KiB

Docker Compose deployment/runbook

Requested configuration

.env includes exactly:

HOST_PORT=8155
PUBLIC_DOMAIN=http://localhost

The actual browser URL is http://localhost:8155. PUBLIC_DOMAIN is the domain origin requested by owner and deliberately has no port. For local URL construction derive PUBLIC_BASE_URL=http://localhost:8155; prefer relative API URLs (/api/v1/...) on the web client. Do not send client requests directly to container name api (not browser-resolvable).

M0 required deliverables

  • apps/web/Dockerfile: multi-stage Node build → lightweight nginx runtime, serving Vite output and forwarding /api/, /health to api:3000. Create nginx config under apps/web/nginx.conf. Use SPA history fallback to index.html; ensure /health and /api/ proxy rules take precedence.
  • apps/server/Dockerfile: multi-stage Node build, Node runtime listening on 0.0.0.0:3000 and health endpoint.
  • compose.yaml is provided; adapt only if necessary for a working, secure Compose setup, preserving exposed host port, private DB/API, healthcheck and volume. If Node native dependencies require extra Docker libraries, document why.
  • Use NODE_ENV=development only for initial local setup; deployment builds should run production assets and API with runtime environment.
  • Implement Drizzle migrations on container initialization as a controlled documented command, not an uncontrolled migration loop. Provide npm run db:migrate, npm run db:seed.
  • docker compose config should parse correctly before Docker build.

Commands

# local bootstrap (after M0 files created)
docker compose config
docker compose up --build -d
docker compose ps
curl -fsS http://localhost:8155/health

# Stop (keep database)
docker compose down

# NEVER use -v unless intentionally deleting data
docker compose down -v

Critical security note

The starter .env has a deliberately weak local-only placeholder password. Generate a strong password before exposing the app or sharing .env. .env is gitignored. In this MVP there is no user authentication: do not open the app to the public internet until auth/access control and API throttling are implemented.

Future reverse proxy

Later replace PUBLIC_DOMAIN with a true HTTPS origin and configure TLS at the reverse proxy; no fixed 8155 should be appended for an external HTTPS origin. Keep Compose HOST_PORT configurable; enable trusted proxy headers only for known proxy. Do not overbuild this now.

Implemented M0 bootstrap

Compose publishes web on loopback (127.0.0.1:${HOST_PORT}:8080), with nginx running as an unprivileged user. API and DB have no published ports. The bootstrap one-shot service uses the API image to run node dist/migrate.js then node dist/seed.js; API waits for successful completion. A PostgreSQL transaction advisory lock serializes migration execution. A migration tracking table prevents repeat schema application. Player seeds use conflict-safe inserts and preserve existing records. The M1 catalog seed synchronizes the current versioned definition; it does not rewrite plant genomes or ancestry.

For explicit reruns use docker compose run --rm bootstrap node dist/migrate.js or docker compose run --rm bootstrap node dist/seed.js. Runtime images contain compiled JavaScript; root npm migration/seed scripts use TypeScript tooling for host development with an explicit DATABASE_URL. Compose production mode overrides the starter development value without modifying .env.