feat: add local docker compose development stack - #144
Merged
Conversation
Provide a one-command local stack (API, wallet-provisioning worker, PostgreSQL, Redis) with health checks, dependency startup, explicit migrations + deterministic seed, project-scoped volumes, and a smoke test. Fixes blocked local development: - prisma.config.ts: fall back to a local DATABASE_URL so `prisma generate` succeeds without a live database (also unblocks the Docker build), and move the seed command into the Prisma 7 config - package.json: add predev/prebuild prisma generate hooks, db:generate, db:deploy, worker:dev, and stack:* scripts - src/config/jwt.ts: import JsonWebTokenError via the jsonwebtoken default export so the server boots under real Node ESM - reorder the learner-preferences migration after first_migration (it referenced `users` before that table existed, failing fresh DBs) - Dockerfile: point the healthcheck at /health/live instead of the 404ing /health path; drop accidentally committed UTF-16 error logs - CI: validate `docker compose config` on every PR Closes learnault#125
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #125
Summary
Adds a reproducible local Docker Compose development stack — API, wallet-provisioning worker, PostgreSQL, and Redis — started with one command. While building it, I found and fixed several things that blocked local development entirely (fresh-install Prisma failures, a crash on boot under real Node ESM, and a migration that always fails on a fresh database).
Changes
Docker Compose stack (#125)
docker-compose.yml—api,worker,db(Postgres 16),redisservicespg_isready,redis-cli ping,/health/live) withdepends_on: service_healthyso readiness waits for dependenciesprisma migrate deploybefore startingpgdata,redisdata) — reset is project-scoped viadocker compose down -vstop_grace_period: 30smatching the app's graceful-shutdown handlerdocker/Dockerfile.dev— dev image: all deps, OpenSSL (for Prisma), generated client; source bind-mounted for nodemon hot reloaddocker/entrypoint-dev-api.sh/docker/entrypoint-dev-worker.sh— explicit migrations + seed, then dev server / workersrc/workers/wallet-provisioning.worker.ts— polls the idempotent wallet-provisioning outbox (Prisma repo + dev in-memory KMS + SDK keypair generator), with SIGTERM/SIGINT graceful shutdownscripts/stack-smoke-test.sh— validates compose config, starts the stack, waits for/health/ready, probes liveness/readiness, prints service status (pnpm stack:smoke;--validatefor config-only)package.json—stack:up/down/reset/logs/validate/smoke,worker:dev,db:generate,db:deploydocs/DEVELOPMENT_STACK.md— quick start, health checks, reset, logs, smoke test, troubleshooting; linked from README.env.example—POSTGRES_*,REDIS_PORT,API_PORT,WORKER_POLL_INTERVAL_MSdocker compose config --quieton every PRFixes found while building the stack
prisma.config.ts—prisma generatefailed without aDATABASE_URL(Prisma'senv()helper throws), which also meant the production Dockerfile build stage could never generate the client. Now falls back to a local default; seed command moved into the Prisma 7 config (migrations.seed)src/config/jwt.ts—import { JsonWebTokenError } from 'jsonwebtoken'crashes the server under real Node ESM (The requested module 'jsonwebtoken' does not provide an export named 'JsonWebTokenError'). Uses the default import instead, matchingsrc/utils/jwt.ts20260718000000_add_learner_preferencesreferencedusersbefore20260719100042_first_migrationcreated it, soprisma migrate deployalways failed on a fresh database (P3009). Renamed to20260719100043_add_learner_preferences(the old one never applied anywhere — it always failed). 100% rename, no SQL changeDockerfile— healthcheck probed/health, which 404s (routes are/health/live+/health/ready); now probes/health/liveserver_error*.txt,lint_results*.txt,lint_output.json) — already excluded by.dockerignoreVerification
pnpm lint— cleantsc --noEmit— cleanpnpm test:ci— 641 passed / 3 skipped (pre-existing DB-requiring skips; no Postgres in unit-test env)docker compose config --quiet— validdocker compose down -v && scripts/stack-smoke-test.sh):GET /health/live→{"status":"ok",...}GET /health/ready→{"status":"ready","checks":{"database":"ok"}}docker compose stop api→ graceful shutdown observed;down -vremoves only project volumes