From 3dd80f91fe39caeab955b7deb5b0ad0c61c52a4f Mon Sep 17 00:00:00 2001 From: implementer Date: Sat, 29 Aug 2026 00:32:15 +0000 Subject: [PATCH] feat: persist the database volume across restart/recreate (E00-S02-T04) Mount the named `db-data` volume at PostgreSQL's data directory (/var/lib/postgresql/data) on the db service and declare it in the top-level volumes map, so the database survives `docker compose restart` and `docker compose down` + `up -d` (recreate). Reset with `docker compose down -v` per the issue rollback note. Header comments in compose.yaml and the server Dockerfile updated: T04 is no longer out of scope; T05/T06 remain. --- apps/server/Dockerfile | 5 +++-- compose.yaml | 23 ++++++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/apps/server/Dockerfile b/apps/server/Dockerfile index 5b9498f..4cc2d96 100644 --- a/apps/server/Dockerfile +++ b/apps/server/Dockerfile @@ -8,8 +8,9 @@ # server answering `GET /health` with `{"status":"ok"}` (HTTP 200) on port # 3000, so the app container stays up and the health endpoint succeeds. The # Fastify 5 application shell (and the real HTTP API) lands in a later story; -# volume persistence (T04), non-root/read-only hardening (T05) and multi-arch -# targets remain later E00-S02 tasks — all out of scope here. +# DB volume persistence (T04) is a Compose-level concern (see compose.yaml — +# this image is unchanged), while non-root/read-only hardening (T05/T06) and +# multi-arch targets remain later E00-S02 tasks — all out of scope here. # # Image base: node:24.19.0-bookworm-slim (glibc Debian) per Technology-Stack # §5.4 — argon2 is a native dependency and musl/Alpine causes native-module diff --git a/compose.yaml b/compose.yaml index 3def6eb..ebcdf89 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,4 +1,4 @@ -# EPPP Docker Compose baseline — [E00-S02-T01/T02/T03] +# EPPP Docker Compose baseline — [E00-S02-T01/T02/T03/T04] # # `docker compose up -d` starts both the database (PostgreSQL) and the # application (@personal-blog/server). Rollback: `docker compose down`. @@ -12,8 +12,14 @@ # `{"status":"ok"}`) on port 3000, so the app container stays up and the # health endpoint succeeds once the stack is running. # -# Explicitly out of scope for T01/T02/T03 (land in later E00-S02 tasks): -# - DB volume persistence (T04) +# Database volume persistence (T04): the `db` service mounts the named volume +# `db-data` at PostgreSQL's data directory (`/var/lib/postgresql/data`), so +# the database survives `docker compose restart` (restart) and +# `docker compose down` + `docker compose up -d` (recreate, which discards the +# container filesystem). Reset the data with `docker compose down -v`. +# +# Explicitly out of scope for T01..T04 (land in later E00-S02 tasks): +# - non-root execution (T05), read-only root filesystem (T06) # # All values have defaults so `docker compose up -d` works from a clean clone # without a .env file (a committed .env.example template lands in E00-S04). @@ -29,6 +35,11 @@ services: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-eppp} ports: - "${POSTGRES_PORT:-5432}:5432" + # T04: persist the database in the named `db-data` volume (PostgreSQL data + # directory), so data survives `docker compose restart` and `docker + # compose down` + `up -d` (recreate). `docker compose down -v` resets it. + volumes: + - db-data:/var/lib/postgresql/data # Health gate for the app service (T02): probe the same credentials the db # service was created with. `$$` defers interpolation to the container, so # POSTGRES_USER/POSTGRES_DB overrides apply to the probe too. @@ -52,3 +63,9 @@ services: depends_on: db: condition: service_healthy + +# Named volumes shared across `docker compose` lifecycles. `db-data` (T04) +# holds the PostgreSQL data directory and is preserved across restart and +# recreate; `docker compose down -v` removes it to reset the database. +volumes: + db-data: