[E00-S02-T01] docker compose up -d starts DB + app #382
No Reviewers
Labels
Clear labels
agent/analyst-drafted
agent/analyst-drafted
needs/human-decision
needs/human-decision
needs/security-review
needs/security-review
tier/t0
tier/t1
tier/t2
tier/t3
kind
bug
kind
bug
kind
epic
kind
epic
kind
initiative
EPPP programme initiative
kind
story
kind
story
kind
task
EPPP engineering card/task decomposed from a story
kind
toil
kind
toil
loop
1
loop
1
loop
2
loop
2
loop
3
loop
3
risk
agent-full
risk
agent-full
risk
human-gated
risk
human-gated
risk
human-only
risk
human-only
size
l
size
l
size
m
size
m
size
s
size
s
status
blocked
status
blocked
status
done
Workflow: Done
status
in-progress
status
in-progress
status
proposed
status
proposed
status
ready
status
ready
status
review
status
review
stream
checkout
stream
checkout
stream
onboarding
stream
onboarding
stream
platform
stream
platform
trivial — implementer only, auto-merge
standard — implementer + reviewer + tester
complex — security if triggered, human merge
critical — full chain + security, human merge
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Fabrika/PersonalBlog#382
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What changed
Establishes the [E00-S02-T01] Docker Compose baseline (#59) so
docker compose up -dstarts both the database and the application from a clean clone, with no.envrequired (all values have defaults).Review round (addresses the two
request-changesfindings on the previous pass):apps/server/Dockerfile— both build and runtime stages moved fromnode:24-alpinetonode:24.19.0-bookworm-slim: the architecture/Technology-Stack doc §5.4 requires a glibc Debian base because argon2 is a native dependency (musl/Alpine causes native-module build surprises).compose.yaml—dbimage moved frompostgres:16-alpinetopostgres:18-bookworm(the PostgreSQL 18 line on Debian bookworm), matching the documented PostgreSQL 18 target (§5.2/§5.4/§6.2 and the §7 golden tuple pin PostgreSQL 18.6).tests/compose-config.test.mjs— assertions updated so the committed state they lock in matches the corrected image bases.Baseline content:
compose.yaml(repo root) — the stack:dbservice:postgres:18-bookworm,POSTGRES_DB/POSTGRES_USER/POSTGRES_PASSWORDwith:-defaults, host port5432published (overridable viaPOSTGRES_PORT);appservice: built from the committedapps/server/Dockerfile,DATABASE_URLpointed at thedbservice (postgres://…@db:5432/…), host port3000published (overridable viaAPP_PORT),depends_on: [db]so the application starts after the database.apps/server/Dockerfile— multi-stage Node 24.19.0 image:buildstage:node:24.19.0-bookworm-slim+ Corepack-enabled pnpm 11.23.0,pnpm install --frozen-lockfile(every workspace manifest copied so the in-image workspace matches the lockfile importers), thenpnpm --filter @personal-blog/server build(tsc→dist/);runtimestage:node:24.19.0-bookworm-slim, copiesnode_modules, compileddist/and the manifest,EXPOSE 3000,CMD ["node", "apps/server/dist/index.js"](the bootstrap placeholder loads and exits 0 — the Fastify shell that turns it into a serving process is a later story)..dockerignore(repo root) — excludes.git,node_modules,dist,.env*, logs from the build context.tests/compose-config.test.mjs— zero-dependencynode:testsuite that locks in both acceptance criteria against the committed state (see table), plus non-vacuous mutation probes and, when a Docker CLI/daemon is present, real-stack probes:docker compose configvalidation and an actualdocker compose up -d→ps→downrun asserting thedbcontainer is up and theappcontainer starts cleanly (skips cleanly where Docker is unavailable).Explicitly out of scope per the brief, not touched: PostgreSQL health gate (E00-S02-T02), app health endpoint (E00-S02-T03), DB volume persistence (E00-S02-T04). No manifests, no lockfile, no CI workflow changes — the frozen-install CI job is unaffected.
Criterion → test table
docker compose up -dstarts the databasetests/compose-config.test.mjs— "the database service is defined sodocker compose up -dstarts the database": the committedcompose.yamldeclares adbservice with the committed PostgreSQL 18 image (postgres:18-bookworm), credentials with defaults, and a published:5432port. Non-vacuous: "removing the db service makes the database criterion fail (mutation probe)" proves the assertion catches a missingdb. When Docker is available, "docker compose up -d starts the database and application containers" runs the real stack and asserts thedbcontainer is runningdocker compose up -dstarts the applicationtests/compose-config.test.mjs— "the application service is defined sodocker compose up -dstarts the application" (appservice: build context.,apps/server/Dockerfile,DATABASE_URL→db, published:3000,depends_on: [db]) and "the application image is defined by a committed multi-stage Dockerfile" (Node 24.19.0 bookworm-slim build+runtime stages, frozen install,pnpm --filter @personal-blog/server build, runtime entrypointnode apps/server/dist/index.js). Non-vacuous: app-removal mutation probe + Dockerfile-without-CMDprobe. When Docker is available, the real-stack probe asserts theappcontainer is created and starts cleanly (exit 0)Test plan executed
node --test tests/compose-config.test.mjs→ 9/9 pass, 2 skipped (Docker probes skip cleanly where no Docker CLI/daemon exists — this sandbox has none) ✓node --test tests/*.test.mjs→ 48 pass / 12 fail / 2 skip; the 12 failures are the pre-existing Node-22-environment ones on pristinemain(nonode_modules,engines.node: 24.xrestriction) — identical to the baseline the previous tester recorded, none caused by this change ✓compose.yamlre-parsed (minimal block-YAML parser + independent structure check):db.image = postgres:18-bookworm,app.buildunchanged ✓docker compose up -dthen confirm DB + app containers start; rollbackdocker compose down— the Docker-gated probe automates exactly this when a daemon is availableRisks / notes
appcontainer starts and exits 0 at T01 becauseapps/serveris still the bootstrap placeholder; the health-gate/health-endpoint stories (T02/T03) turn it into a staying-up process. The integration probe therefore asserts a clean exit (0) forappand running fordb.postgres:18-bookwormis the floating 18.x tag per the review direction; the doc §5.4 exact-minor pin (postgres:18.6-bookworm) is the provenance-verified target for later provenance re-runs (§5.2.1), and18-bookwormis the same 18.x line on Debian bookworm.skipwhendocker/the Compose plugin/daemon are unavailable, so the suite stays green on Docker-less machines while giving real end-to-end validation where Docker exists..dockerignorekeeps local artifacts out of the build context; a committed.env.exampletemplate remains out of scope (E00-S04).Refs #168