build(docker): add core application image
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
# Container Packaging Task 3 Report
|
||||
|
||||
## Status
|
||||
|
||||
Implemented the multi-stage core application image, non-root runtime, pinned Pi installation,
|
||||
container entrypoint, context exclusions, and an in-image health smoke test.
|
||||
|
||||
## TDD / Build Evidence
|
||||
|
||||
Initial RED:
|
||||
|
||||
```text
|
||||
docker build -f docker/core.Dockerfile -t thothii-core:test .
|
||||
ERROR: failed to build: resolve : lstat docker: no such file or directory
|
||||
```
|
||||
|
||||
The first sandboxed attempt could not access the Docker socket; the authorized rerun reached the
|
||||
builder and failed for the expected reason: the Dockerfile did not exist.
|
||||
|
||||
GREEN build:
|
||||
|
||||
```text
|
||||
sh -n docker/core-entrypoint.sh docker/smoke/core-smoke.sh
|
||||
docker build --progress=plain -f docker/core.Dockerfile -t thothii-core:test .
|
||||
```
|
||||
|
||||
Result: shell syntax exited 0; Docker build exited 0. A final rebuild after tightening
|
||||
`.dockerignore` also exited 0 and transferred only 17.60 kB of changed context (the initial clean
|
||||
build transferred 1.02 MB).
|
||||
|
||||
## Runtime and Entrypoints
|
||||
|
||||
- Runtime user is `10001:10001` (`thoth`), never root.
|
||||
- Runtime contains Node `v22.19.0` and Python `3.12.13`. Python 3.12 is intentional because the
|
||||
harness declares `requires-python = ">=3.12"` and also satisfies the deployment floor of 3.11+.
|
||||
- Pi is installed exactly as `@earendil-works/pi-coding-agent@0.80.3`; its build-time and runtime
|
||||
version probes both reported `0.80.3`.
|
||||
- `server` starts `/app/backend/dist/server.js`; `doctor` routes to `tht doctor`; `preprocess`
|
||||
routes to the future-facing `tht preprocess` command; explicit `tht ...` and arbitrary CLI
|
||||
arguments route to the installed `tht` binary.
|
||||
- The gate extension's `typebox` runtime dependency is installed from the harness lockfile.
|
||||
|
||||
## Smoke and Diagnostic Results
|
||||
|
||||
```text
|
||||
docker run --rm thothii-core:test doctor
|
||||
config: error - configuration is invalid or unreadable
|
||||
data_root: ok
|
||||
```
|
||||
|
||||
Result: expected exit 1 for absent mounted workspace configuration, with no traceback and no
|
||||
secret-bearing validation detail.
|
||||
|
||||
```text
|
||||
docker run --rm --entrypoint /app/docker/smoke/core-smoke.sh thothii-core:test
|
||||
backend listening on http://127.0.0.1:8787
|
||||
v22.19.0
|
||||
Python 3.12.13
|
||||
core smoke: ok
|
||||
```
|
||||
|
||||
Result: exit 0. The script asserted non-root execution, `tht --help`, `pi --version`, runtime
|
||||
version floors, and `GET /health` through curl. Fastify's returned display address was loopback;
|
||||
the inspected container environment is `HOST=0.0.0.0`, and the compiled server passes that value
|
||||
to `app.listen`.
|
||||
|
||||
```text
|
||||
docker run --rm thothii-core:test tht --version
|
||||
0.1.0
|
||||
```
|
||||
|
||||
Result: arbitrary `tht` entrypoint exited 0.
|
||||
|
||||
An explicit runtime assertion checked UID 10001, exact Node and Pi versions, Python 3.11+, and the
|
||||
absence of `/app/harness/.env` and `/app/harness/workspaces`; it exited 0.
|
||||
|
||||
## Image Size and Containment Inspection
|
||||
|
||||
```text
|
||||
docker image inspect thothii-core:test --format '{{.Size}} {{json .Config.User}} {{json .Config.Env}}'
|
||||
221419008 "10001:10001" [...runtime paths and version metadata only...]
|
||||
```
|
||||
|
||||
Image size: **221,419,008 bytes** (about 211.2 MiB).
|
||||
|
||||
`docker history --no-trunc thothii-core:test` was inspected. It contains only Dockerfile commands,
|
||||
the pinned public package name/version, base-image metadata, and non-sensitive runtime variables;
|
||||
no credentials or customer paths were found. An in-image filename scan found only
|
||||
`/app/harness/.pi/settings.json` among `.env`, key/certificate, and settings-name candidates; that
|
||||
tracked Pi file contains theme/startup preferences, not secrets. The build asserts `.env` and
|
||||
workspace directories are absent.
|
||||
|
||||
`.dockerignore` excludes VCS/agent state, all environment files except examples, package-manager
|
||||
credential files, SSH/private-key and certificate formats, local virtualenvs/node_modules/caches,
|
||||
backend runtime data, customer workspaces, sessions, artifacts, indexes, corpus, and deployment
|
||||
mount content.
|
||||
|
||||
## Self-review
|
||||
|
||||
- `git diff --check` is clean.
|
||||
- Entrypoint processes use `exec`, preserving container signal handling.
|
||||
- Backend production dependencies are pruned; TypeScript build tools remain in the build stage.
|
||||
- The writable `/data` root is owned by UID 10001; application payload remains root-owned and
|
||||
read-only to the runtime user.
|
||||
- CA certificates and curl are present for HTTPS integrations and health probing.
|
||||
- No existing source, customer workspace, secret, or unrelated progress-ledger change is included
|
||||
in the task commit.
|
||||
|
||||
## Concerns
|
||||
|
||||
- The `tht preprocess` command is deliberately a future-facing routing contract; its CLI group is
|
||||
scheduled in the Evidence/preprocessing plan and is not implemented in the current harness.
|
||||
- Python dependencies are range-resolved because the existing harness has no Python lockfile. The
|
||||
Pi package, Node runtime, and package-lock-backed Node dependency sets are pinned/reproducible.
|
||||
- The image was built and smoked on Docker Desktop arm64. The chosen official multi-arch base
|
||||
images and Pi package are architecture-neutral at the package level, but amd64 still needs a CI
|
||||
build/smoke before being advertised as verified.
|
||||
Reference in New Issue
Block a user