feat(docker): Dockerfile + entrypoint for home-ctr-onyx image (#28) #32

Merged
archeious merged 1 commit from feat/dockerfile into main 2026-04-19 17:32:08 -06:00
Collaborator

Closes #28. Unblocks #29 (compose.yml) and #30 (Forgejo Actions deploy).

Summary

  • Dockerfile at repo root: python:3.12-slim-bookworm, uv pinned at
    0.5.11 via ghcr.io/astral-sh/uv, uv sync --no-dev --frozen in
    two layers for cache friendliness, USER 1000:1000, EXPOSE 8000,
    HEALTHCHECK against /healthz using python -c + urllib
    (python-slim has no curl).
  • docker/entrypoint.sh: runs alembic upgrade head (the pre-upgrade
    backup hook in alembic/env.py fires automatically), then
    exec uvicorn quartermaster.main:app --host 0.0.0.0 --port 8000 --log-config src/quartermaster/logconfig.json so access + error
    logs land on stdout as JSON. exec makes uvicorn PID 1 for signal
    handling.
  • .dockerignore: trims context (keeps README.md because hatchling
    reads it when installing the local project).
  • README gets a "Docker" section with a representative
    docker build / docker run pair that uses a bind-mounted tempdir
    and a sqlite:////data/qm.db DB URL.

Test plan

  • docker build -t quartermaster:dev . succeeds on a clean context
  • docker run with -v /tmp/qm-data:/data and
    QUARTERMASTER_DB_URL=sqlite:////data/qm.db starts cleanly;
    alembic runs all five migrations
  • curl http://127.0.0.1:8000/healthz returns {"status":"ok"}
  • docker inspect reports Health.Status = healthy
  • Container processes run as uid=1000 gid=1000
  • Access + error logs appear as JSON on stdout (logconfig.json
    honored)
  • The SQLite file lands in the bind mount owned 1000:1000
Closes #28. Unblocks #29 (compose.yml) and #30 (Forgejo Actions deploy). ## Summary - `Dockerfile` at repo root: `python:3.12-slim-bookworm`, uv pinned at `0.5.11` via `ghcr.io/astral-sh/uv`, `uv sync --no-dev --frozen` in two layers for cache friendliness, `USER 1000:1000`, `EXPOSE 8000`, `HEALTHCHECK` against `/healthz` using `python -c` + `urllib` (python-slim has no curl). - `docker/entrypoint.sh`: runs `alembic upgrade head` (the pre-upgrade backup hook in `alembic/env.py` fires automatically), then `exec uvicorn quartermaster.main:app --host 0.0.0.0 --port 8000 --log-config src/quartermaster/logconfig.json` so access + error logs land on stdout as JSON. `exec` makes uvicorn PID 1 for signal handling. - `.dockerignore`: trims context (keeps `README.md` because hatchling reads it when installing the local project). - README gets a "Docker" section with a representative `docker build` / `docker run` pair that uses a bind-mounted tempdir and a `sqlite:////data/qm.db` DB URL. ## Test plan - [x] `docker build -t quartermaster:dev .` succeeds on a clean context - [x] `docker run` with `-v /tmp/qm-data:/data` and `QUARTERMASTER_DB_URL=sqlite:////data/qm.db` starts cleanly; alembic runs all five migrations - [x] `curl http://127.0.0.1:8000/healthz` returns `{"status":"ok"}` - [x] `docker inspect` reports `Health.Status = healthy` - [x] Container processes run as `uid=1000 gid=1000` - [x] Access + error logs appear as JSON on stdout (`logconfig.json` honored) - [x] The SQLite file lands in the bind mount owned `1000:1000`
claude-code added 1 commit 2026-04-19 17:23:03 -06:00
Produces a python:3.12-slim-bookworm image that runs migrations (with
the pre-upgrade backup hook) then uvicorn under uid/gid 1000:1000, as
required by the /mnt/quartermaster/ bind mount on the deploy host.
HEALTHCHECK hits /healthz; uvicorn is pointed at logconfig.json so
access logs land on stdout as JSON.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
archeious merged commit 35f0c8fd79 into main 2026-04-19 17:32:08 -06:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: archeious/quartermaster#32
No description provided.