chore(docker): label the image with its version so status.sh can report it

scripts/status.sh --deployed-version reads org.opencontainers.image.version and
the image carried no such label, so on 2026-08-18 it correctly answered
"unknown" and the digest was the only way to tell one deploy from another. Step
3 of the incident runbook depends on that command.

ARG APP_VERSION defaults to 0.9.3 and can be overridden at build time.

Verified by building: docker build succeeds and
`docker image inspect --format '{{json .Config.Labels}}'` reports
org.opencontainers.image.version = 0.9.3, plus title and source.

Takes effect on the next image build. OPERATIONS.md says so rather than
implying the running container has it — it does not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Neo 2026-08-18 02:34:27 -05:00
parent 9fdc6b6032
commit 77d5131473
2 changed files with 21 additions and 7 deletions

View File

@ -83,6 +83,16 @@ COPY --from=builder /app/server ./server
# Copy compiled native modules from native-deps stage (no build tools in final image) # Copy compiled native modules from native-deps stage (no build tools in final image)
COPY --from=native-deps /app/node_modules ./node_modules COPY --from=native-deps /app/node_modules ./node_modules
# Image metadata. org.opencontainers.image.version is the one that matters
# operationally: scripts/status.sh --deployed-version reads exactly this label,
# and without it the honest answer to "which version is running?" is "unknown" —
# which is what it reported on 2026-08-18, leaving the digest as the only way to
# tell one deploy from another. docs/OPERATIONS.md step 3 depends on it.
ARG APP_VERSION=0.9.3
LABEL org.opencontainers.image.version="$APP_VERSION" \
org.opencontainers.image.title="Queue North Website" \
org.opencontainers.image.source="https://dream.scheller.ltd/null/Queue-North-Website"
# Expose backend port # Expose backend port
EXPOSE 3001 EXPOSE 3001

View File

@ -180,18 +180,22 @@ change anything.
not a healthy service, and reads as "running" in every tool that shows only a not a healthy service, and reads as "running" in every tool that shows only a
state. state.
2. **What is it saying?** `bash scripts/status.sh --logs 200`. 2. **What is it saying?** `bash scripts/status.sh --logs 200`.
3. **Is the deployed version the one you think?** `bash scripts/status.sh` 3. **Is the deployed version the one you think?**
prints the image digest. **`--deployed-version` cannot answer here** — the
image carries no `org.opencontainers.image.version` label, so the script
correctly reports the version as unknown rather than guessing. Compare the
**digest** against the registry instead:
```bash ```bash
bash scripts/status.sh --deployed-version
bash scripts/status.sh | grep digest bash scripts/status.sh | grep digest
``` ```
Adding that label at build time would make this step a one-liner and is worth **The image running today carries no `org.opencontainers.image.version`
doing next time the Dockerfile is touched. label**, so the first command correctly reports the version as unknown rather
than guessing, and the digest is the only way to tell one deploy from
another. The label was added to the `Dockerfile` on 2026-08-18 and takes
effect on the next build — until an image built after that date is deployed,
use the digest.
Non-zero from `--deployed-version` means it could not be read at all. Stop
there rather than assuming.
4. **Is it the database?** `/api/health` returns 503 with `db: error` when the 4. **Is it the database?** `/api/health` returns 503 with `db: error` when the
`SELECT 1` fails. That is a real answer and not an outage of the whole site: `SELECT 1` fails. That is a real answer and not an outage of the whole site:
the marketing pages keep serving while every form submission is failing. the marketing pages keep serving while every form submission is failing.