Files
directus/.planning/phase-1-slice-1-schema/07-image-and-dockerfile.md
T
julian a8e808e71c Scaffold directus service planning structure
Initial commit. Establishes the .planning/ tree mirroring processor's
shape (ROADMAP.md as nav hub + per-phase folders with READMEs and
granular task files).

Six phases:

1. Slice 1 schema + deploy pipeline — what Rally Albania 2026 needs.
   Org catalog (orgs, users, vehicles, devices) + event participation
   (events, classes, entries, entry_crew, entry_devices). db-init/
   for the positions hypertable + faulty column. snapshot/apply
   tooling. Gitea CI dry-run. Dogfood seed of Rally Albania 2026.
   Nine task files with full Goal / Deliverables / Specification /
   Acceptance criteria / Risks / Done sections.

2. Course definition — stages, segments, geofences, waypoints, SLZs.
   PostGIS extension introduced here.

3. Timing & penalty tables — co-developed with processor Phase 2.
   entry_segment_starts, entry_crossings, entry_penalties,
   stage_results, penalty_formulas.

4. Permissions & policies — Directus 11 dynamic-filter Policies per
   logical role. Deployment-time work, deferred to keep early phases
   focused on the data model.

5. Custom extensions — TypeScript hooks/endpoints implementing the
   cross-plane workflows the schema implies (faulty-flag → Redis
   stream emit, stage-open materializer, etc.).

6. Future / optional — retroactivity preview UI, command-routing
   Flows, audit trails, federation rule import. Not committed.

Non-negotiable design rules captured in ROADMAP.md: schema authority
in Directus + snapshot-as-code + db-init for non-Directus DDL +
sequential idempotent migrations + entrypoint apply order + no
application logic in Flows + permissions deferred to Phase 4.

Architectural anchors point at the wiki at ../docs/wiki/ — the schema
draft, the Rally Albania 2025 source page, plus the existing
processor/postgres-timescaledb/live-channel pages. Each task file
calls out the wiki refs an implementing agent should read first.

README.md mirrors the processor service README structure: quick start,
local Docker test, prod/stage deployment notes, env vars, CI behavior.
2026-05-01 20:42:44 +02:00

4.5 KiB

Task 1.7 — Image build & entrypoint

Phase: 1 — Slice 1 schema + deploy pipeline Status: Not started Depends on: 1.2, 1.3, 1.6 (need the runner, migrations, and snapshot tooling all in place) Wiki refs: docs/wiki/entities/directus.md (Schema management section)

Goal

Build a production-ready Directus image that bakes in the snapshot, db-init migrations, extensions directory, and entrypoint script. Replace the placeholder entrypoint from 1.1 with the real boot sequence: db-init → schema apply → directus start.

Deliverables

  • Dockerfile (replacing the placeholder from 1.1):
    FROM directus/directus:11.5.1   # pin specific patch version
    
    USER root
    RUN apk add --no-cache postgresql16-client bash coreutils
    USER node
    
    COPY --chown=node:node snapshots/  /directus/snapshots/
    COPY --chown=node:node db-init/    /directus/db-init/
    COPY --chown=node:node extensions/ /directus/extensions/
    COPY --chown=node:node scripts/    /directus/scripts/
    COPY --chown=node:node entrypoint.sh /directus/entrypoint.sh
    RUN chmod +x /directus/entrypoint.sh /directus/scripts/*.sh
    
    ENTRYPOINT ["/directus/entrypoint.sh"]
    
    Adjust apk / apt-get based on the upstream image's distro. postgresql-client is required for psql in the db-init runner.
  • entrypoint.sh:
    #!/usr/bin/env bash
    set -euo pipefail
    
    echo "[entrypoint] running db-init"
    /directus/scripts/apply-db-init.sh
    
    echo "[entrypoint] applying Directus schema snapshot"
    /directus/scripts/schema-apply.sh
    
    echo "[entrypoint] starting Directus"
    exec /directus/cli.js start
    
    (Verify /directus/cli.js start is the correct upstream command for the pinned version. Some versions use node /directus/server.js.)
  • Update compose.dev.yaml so the dev image uses the same Dockerfile (no special path in dev). The local image has identical boot semantics to prod — only env vars differ.

Specification

  • Pin the Directus version exactly (e.g. 11.5.1, not 11). Version bumps land via PR.
  • Layer ordering for cache friendliness.
    1. FROM + apk install (rarely changes).
    2. COPY scripts/ (changes occasionally).
    3. COPY entrypoint.sh (rarely changes).
    4. COPY db-init/ (changes per migration PR).
    5. COPY snapshots/ (changes per schema PR — most volatile).
    6. COPY extensions/ (Phase 5+). Putting the most-changed layer last maximizes cache reuse for the rest.
  • USER node for runtime (matches upstream image's non-root convention).
  • Health check. Add a HEALTHCHECK instruction calling wget -qO- http://localhost:8055/server/ping (or the upstream's health endpoint), with sensible interval/timeout. Useful in compose and Portainer.
  • Entrypoint failure modes. If db-init fails → exit, container restarts (Docker will retry). If schema apply fails → same. Both failures should produce clear log lines so an operator looking at Portainer logs can diagnose.
  • No EXPOSE change — the upstream image already exposes 8055.
  • No ENV overrides for Directus runtime config in the Dockerfile — that's the deployer's concern via env vars at runtime.

Acceptance criteria

  • docker build -t trm-directus:dev . succeeds.
  • Image size is reasonable (< 600 MB; upstream image + tooling).
  • Booting against a fresh Postgres: db-init applies all three migrations, schema apply creates 12 collections, Directus starts and serves on :8055.
  • Re-booting against the same Postgres (warm DB): db-init reports "0 applied, 3 skipped", schema apply reports "no changes", Directus starts.
  • Killing Postgres mid-db-init → container exits non-zero with clear error in logs.
  • Killing Postgres mid-schema-apply → container exits non-zero with clear error in logs.
  • HEALTHCHECK reports "healthy" once Directus is serving.
  • compose.dev.yaml directus service uses the local Dockerfile build and works end-to-end (pnpm dev:reset → fresh boot → admin UI loads).

Risks / open questions

  • Upstream image distro. Directus's official image has used both Alpine and Debian-based bases over the years. Verify the current 11.x base and adjust apk vs apt-get accordingly.
  • /directus/cli.js start path. Confirm against the upstream Dockerfile / docs for the pinned version. Bake the right command into entrypoint.sh.
  • Permissions on /directus/snapshots/ etc. If the upstream user is node (uid 1000), the --chown=node:node flag is right. Verify with docker run --rm trm-directus:dev id.

Done

(Fill in commit SHA + one-line note when this lands.)