fix: align app/db image bases with documented stack (E00-S02-T01)
CI / Frozen lockfile install (pull_request) Successful in 48s
CI / Frozen lockfile install (pull_request) Successful in 48s
Switch the app image from node:24-alpine to node:24.19.0-bookworm-slim in both build and runtime stages (Technology-Stack 5.4: glibc Debian base required because argon2 is a native dependency; musl/Alpine causes native-module build surprises), and the db image from postgres:16-alpine to postgres:18-bookworm (Technology-Stack 5.2/5.4/6.2 + golden tuple 7 pin PostgreSQL 18.6; 18-bookworm is the 18.x line on Debian bookworm). Update tests/compose-config.test.mjs so the committed assertions lock in the corrected image bases (db image, Dockerfile build/runtime stages, parser probe).
This commit is contained in:
@@ -3,15 +3,19 @@
|
|||||||
# @personal-blog/server — EPPP public server application image.
|
# @personal-blog/server — EPPP public server application image.
|
||||||
#
|
#
|
||||||
# [E00-S02-T01] baseline: builds the workspace server package with the pinned
|
# [E00-S02-T01] baseline: builds the workspace server package with the pinned
|
||||||
# toolchain (Node 24 + pnpm 11.23.0, frozen lockfile) and runs the compiled
|
# toolchain (Node 24.19.0 + pnpm 11.23.0, frozen lockfile) and runs the compiled
|
||||||
# entrypoint. The server is still a bootstrap placeholder (its module loads and
|
# entrypoint. The server is still a bootstrap placeholder (its module loads and
|
||||||
# exits cleanly); the Fastify 5 application shell that turns it into a serving
|
# exits cleanly); the Fastify 5 application shell that turns it into a serving
|
||||||
# process lands in a later story, and the health gate (T02), health endpoint
|
# process lands in a later story, and the health gate (T02), health endpoint
|
||||||
# (T03), volume persistence (T04), non-root/read-only hardening and multi-arch
|
# (T03), volume persistence (T04), non-root/read-only hardening and multi-arch
|
||||||
# targets are later E00-S02 tasks — all out of scope here.
|
# targets are 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
|
||||||
|
# build surprises, so the image must stay on a glibc base.
|
||||||
|
|
||||||
# --- build stage: install the frozen workspace and compile the server --------
|
# --- build stage: install the frozen workspace and compile the server --------
|
||||||
FROM node:24-alpine AS build
|
FROM node:24.19.0-bookworm-slim AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Enable the pinned pnpm (11.23.0, via packageManager in the root package.json)
|
# Enable the pinned pnpm (11.23.0, via packageManager in the root package.json)
|
||||||
@@ -33,8 +37,8 @@ RUN pnpm install --frozen-lockfile
|
|||||||
COPY apps/server apps/server
|
COPY apps/server apps/server
|
||||||
RUN pnpm --filter @personal-blog/server build
|
RUN pnpm --filter @personal-blog/server build
|
||||||
|
|
||||||
# --- runtime stage: Node 24 + compiled output only ----------------------------
|
# --- runtime stage: Node 24.19.0 (bookworm-slim) + compiled output only ------
|
||||||
FROM node:24-alpine AS runtime
|
FROM node:24.19.0-bookworm-slim AS runtime
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -13,7 +13,9 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres:16-alpine
|
# PostgreSQL 18 on Debian bookworm — the documented runtime target
|
||||||
|
# (Technology-Stack §5.2/§5.4/§6.2, golden tuple §7; no Alpine drift).
|
||||||
|
image: postgres:18-bookworm
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-eppp}
|
POSTGRES_DB: ${POSTGRES_DB:-eppp}
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-eppp}
|
POSTGRES_USER: ${POSTGRES_USER:-eppp}
|
||||||
|
|||||||
@@ -13,8 +13,9 @@
|
|||||||
* container is up.
|
* container is up.
|
||||||
* - "docker compose up -d starts the application" → the committed
|
* - "docker compose up -d starts the application" → the committed
|
||||||
* `compose.yaml` declares an `app` service built from the committed
|
* `compose.yaml` declares an `app` service built from the committed
|
||||||
* `apps/server/Dockerfile` (multi-stage: Node 24 + frozen pnpm install →
|
* `apps/server/Dockerfile` (multi-stage: Node 24.19.0 bookworm-slim +
|
||||||
* `tsc` build of `@personal-blog/server` → `node apps/server/dist/index.js`),
|
* frozen pnpm install → `tsc` build of `@personal-blog/server` →
|
||||||
|
* `node apps/server/dist/index.js`),
|
||||||
* with a published default port and `depends_on: db` so the application
|
* with a published default port and `depends_on: db` so the application
|
||||||
* starts after the database. The real-stack probe asserts the `app`
|
* starts after the database. The real-stack probe asserts the `app`
|
||||||
* container is created and starts cleanly (exit 0 when the placeholder
|
* container is created and starts cleanly (exit 0 when the placeholder
|
||||||
@@ -158,8 +159,8 @@ function assertDbService(compose) {
|
|||||||
assert.ok(db, 'compose.yaml must declare a "db" service (docker compose up -d starts the database)');
|
assert.ok(db, 'compose.yaml must declare a "db" service (docker compose up -d starts the database)');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
db.image,
|
db.image,
|
||||||
'postgres:16-alpine',
|
'postgres:18-bookworm',
|
||||||
'the "db" service must use the committed PostgreSQL image (postgres:16-alpine)',
|
'the "db" service must use the committed PostgreSQL 18 image (postgres:18-bookworm)',
|
||||||
);
|
);
|
||||||
const env = db.environment ?? {};
|
const env = db.environment ?? {};
|
||||||
assert.equal(env.POSTGRES_DB, '${POSTGRES_DB:-eppp}', 'db must set POSTGRES_DB (with a default)');
|
assert.equal(env.POSTGRES_DB, '${POSTGRES_DB:-eppp}', 'db must set POSTGRES_DB (with a default)');
|
||||||
@@ -291,13 +292,13 @@ test('the application image is defined by a committed multi-stage Dockerfile', (
|
|||||||
const dockerfile = read(DOCKERFILE_PATH);
|
const dockerfile = read(DOCKERFILE_PATH);
|
||||||
assert.match(
|
assert.match(
|
||||||
dockerfile,
|
dockerfile,
|
||||||
/FROM node:24-alpine AS build/,
|
/FROM node:24\.19\.0-bookworm-slim AS build/,
|
||||||
'the Dockerfile must build on the committed Node 24 line (FROM node:24-alpine AS build)',
|
'the Dockerfile must build on the committed Node 24.19.0 bookworm-slim base (FROM node:24.19.0-bookworm-slim AS build)',
|
||||||
);
|
);
|
||||||
assert.match(
|
assert.match(
|
||||||
dockerfile,
|
dockerfile,
|
||||||
/FROM node:24-alpine AS runtime/,
|
/FROM node:24\.19\.0-bookworm-slim AS runtime/,
|
||||||
'the Dockerfile must ship a slim Node 24 runtime stage (FROM node:24-alpine AS runtime)',
|
'the Dockerfile must ship a Node 24.19.0 bookworm-slim runtime stage (FROM node:24.19.0-bookworm-slim AS runtime)',
|
||||||
);
|
);
|
||||||
assert.match(
|
assert.match(
|
||||||
dockerfile,
|
dockerfile,
|
||||||
@@ -394,7 +395,7 @@ test('the YAML parser reads the committed structure (non-vacuous parser probe)',
|
|||||||
const parsed = parseYaml(`
|
const parsed = parseYaml(`
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres:16-alpine
|
image: postgres:18-bookworm
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: eppp
|
POSTGRES_DB: eppp
|
||||||
ports:
|
ports:
|
||||||
@@ -406,7 +407,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
`);
|
`);
|
||||||
assert.equal(parsed.services.db.image, 'postgres:16-alpine');
|
assert.equal(parsed.services.db.image, 'postgres:18-bookworm');
|
||||||
assert.equal(parsed.services.db.environment.POSTGRES_DB, 'eppp');
|
assert.equal(parsed.services.db.environment.POSTGRES_DB, 'eppp');
|
||||||
assert.deepEqual(parsed.services.db.ports, ['5432:5432']);
|
assert.deepEqual(parsed.services.db.ports, ['5432:5432']);
|
||||||
assert.equal(parsed.services.app.build.dockerfile, 'apps/server/Dockerfile');
|
assert.equal(parsed.services.app.build.dockerfile, 'apps/server/Dockerfile');
|
||||||
|
|||||||
Reference in New Issue
Block a user