Task 1.1 — Project scaffold

Phase 1 task 1.1 lands. Directus 11.17.4 boots locally end-to-end
against a TimescaleDB+PostGIS container; admin UI serves at :8055,
admin bootstrap from env vars works, named volumes preserve data
across down/up cycles.

Scaffold:
- Dockerfile — FROM directus/directus:11.17.4. Pre-installs
  postgresql16-client (ahead of task 1.2's db-init runner needing psql).
  Bakes in /directus/snapshots, /directus/db-init, /directus/scripts,
  /directus/extensions, /directus/entrypoint.sh.
- compose.dev.yaml — db (timescale/timescaledb-ha:pg16.6-ts2.17.2-all)
  + directus (local build), healthchecks, named volumes
  directus-pg-data + directus-uploads.
- entrypoint.sh — placeholder using upstream's actual flow
  (node cli.js bootstrap && pm2-runtime start ecosystem.config.cjs);
  the real db-init -> schema apply -> start wrapper lands in task 1.7.
- package.json — scripts-only (dev, dev:down, dev:reset,
  schema:snapshot, schema:apply, db:init), no runtime deps.
- .env.example — sectioned, fully documented, KEY/SECRET marked
  required with generation hints.
- .gitignore, .dockerignore — match the processor service conventions.
- snapshots/, db-init/, scripts/, extensions/ — empty with .gitkeep,
  filled by later Phase 1 tasks (1.3, 1.6) and Phase 5.

Lessons locked in (against the empirical pnpm dev boot):
- timescale/timescaledb-ha:pg16-latest does NOT exist on Docker Hub.
  Pin a concrete version (we used pg16.6-ts2.17.2-all).
- This image's data directory is /home/postgres/pgdata/data, not
  /pgdata or /var/lib/postgresql/data. PGDATA env var and the volume
  mount must both target it.
- The -all variant bundles PostGIS binaries but the extension is not
  auto-created on the directus database; CREATE EXTENSION lands in
  Phase 2 alongside the geofences/SLZs/waypoints collections.
- The upstream image's CMD is bootstrap + pm2-runtime, not a simple
  cli.js start. Bypassing pm2 would lose crash recovery.

These corrections folded into 01-project-scaffold.md (deliverable line
+ Done section), 08-gitea-ci-dryrun.md (CI service tag), and the
inline comments in compose.dev.yaml so future implementers don't
re-discover them.

Status: ROADMAP marks 1.1 done, Phase 1 in progress, 1.2 next.
This commit is contained in:
2026-05-01 21:29:00 +02:00
parent a8e808e71c
commit 387c3c4cfa
16 changed files with 389 additions and 8 deletions
+45
View File
@@ -0,0 +1,45 @@
# syntax=docker/dockerfile:1.7
#
# TRM directus service image.
#
# Single-stage build for Phase 1. A multi-stage build (with a Node builder for
# extensions) lands in Phase 5 when TypeScript extensions are introduced.
#
# Artifacts baked into the image at build time:
# /directus/snapshots/ — schema.yaml (generated; empty placeholder in Phase 1)
# /directus/db-init/ — numbered SQL migration files (Phase 1 task 1.3 fills these)
# /directus/scripts/ — shell helpers (Phase 1 tasks 1.2, 1.6 fill these)
# /directus/extensions/ — TypeScript extensions (Phase 5)
# /directus/entrypoint.sh — boot wrapper (real flow lands in Phase 1 task 1.7)
#
# No bind mounts of these directories in compose.dev.yaml — the image is the
# source of truth. Reproducible across local, CI, and production environments.
FROM directus/directus:11.17.4
# Switch to root only for the setup steps; Directus's upstream image already
# drops to a non-root user — we preserve that for runtime.
USER root
# Install postgresql-client so scripts/apply-db-init.sh can use psql.
# Phase 1 task 1.2 writes the runner; we pre-install the dependency now so
# the image build never needs internet access at runtime.
RUN apk add --no-cache postgresql16-client
# ---- Copy baked-in artifacts ----
# Each COPY is conditional on the directory existing at build time.
# .gitkeep files ensure the directories always exist so COPY never fails.
COPY snapshots/ /directus/snapshots/
COPY db-init/ /directus/db-init/
COPY scripts/ /directus/scripts/
COPY extensions/ /directus/extensions/
COPY entrypoint.sh /directus/entrypoint.sh
# Ensure the entrypoint is executable inside the image regardless of the host
# filesystem's permission bits.
RUN chmod +x /directus/entrypoint.sh
# Drop back to the non-root user the upstream image uses.
USER node
ENTRYPOINT ["/directus/entrypoint.sh"]