Skip to content

Docker + compose packaging, and a home for the artifacts - #272

Merged
rvnminers-A-and-N merged 1 commit into
mainfrom
feat/packaging-and-v0.2.0
Jul 30, 2026
Merged

rvnminers-A-and-N merged 1 commit into
mainfrom
feat/packaging-and-v0.2.0

Conversation

@rvnminers-A-and-N

Copy link
Copy Markdown
Collaborator

Closes #19. Closes #20.

Flavormancer could only run on the machine it was built on. This makes it installable.

Dockerfile β€” a runtime image, not a training one

Training needs 32 cores and hours; serving needs neither. The ~1 GB of trained forests and parquet tables mount at run time instead of baking into a layer that would go stale the moment a head is retrained. Base is slim-bookworm rather than alpine because RDKit ships manylinux wheels that want glibc. Runs unprivileged; health check allows a 180s start period because a cold start genuinely loads 190 heads.

Compose β€” one box, deliberately

Compose and not Kubernetes: one machine, a handful of users, which is the real shape of an on-prem install for a flavour house. Postgres is the pgvector image because the substitution index is a nearest-neighbour search over the 177-dimension profile vector (#20). The schema keeps tox out of that vector β€” safety isn't a flavour-match dimension and must not steer "what tastes similar".

The interesting bug, caught in review

Every artifact path in predict.py/app.py was working-directory relative, because the systemd deployment has always had code and models in one folder. That makes the obvious mount impossible: any bind reaching the models would also shadow app.py, and the container would start with no application code.

I wrote that exact bug into the first draft of this compose file and caught it reviewing the mount line.

Fix: artifacts resolve through predict.artifact() under FLAVORMANCER_HOME, defaulting to ".".

unset resolves to CWD β€” existing systemd deploy byte-for-byte unaffected
set redirects β€” container bakes code in, mounts data

Verified both directions; full suite passes either way.

Not verified

Docker is not installed on the build box, so the image has not been built and run end to end. The compose file parses, the schema is plain SQL, and the path logic is tested β€” but the first real docker compose up should be treated as the test, not as a confirmation. Saying so plainly rather than implying it's proven.

Also

CHANGELOG.md seeded, with v0.2.0 written up and known limits stated (the incoherent heads, the 58 still indicative, Track B not yet running).

  • ruff clean; suite 43 passed

…#19, #20)

Flavormancer could only run on the machine it was built on. This makes it installable.

Dockerfile is deliberately a RUNTIME image. Training needs 32 cores and hours; serving needs
neither, so the ~1 GB of trained forests and parquet tables mount at run time instead of baking
into a layer that would go stale the moment a head is retrained. Base is slim-bookworm rather than
alpine because RDKit ships manylinux wheels that want glibc, and building it on musl is hours of
pain for nothing. Runs unprivileged; the health check allows a 180s start period because a cold
start genuinely loads 190 heads.

docker-compose.yml is Compose and not Kubernetes on purpose β€” one box, a handful of users, which
is the real shape of an on-prem install for a flavour house. Postgres is the pgvector image
because the substitution index is a nearest-neighbour search over the 177-dimension profile
vector, which is exactly what pgvector exists for (#20). The schema in infra/initdb keeps tox OUT
of that vector: safety is not a flavour-match dimension and must not steer "what tastes similar".

The interesting part is FLAVORMANCER_HOME. Every artifact path in predict.py and app.py was
relative to the working directory, because the systemd deployment has always had code and models
sharing one folder. That makes the obvious container mount impossible: any bind reaching the
models would also shadow app.py, and the container would start with no application code. I wrote
that exact bug into the first draft of the compose file and caught it reviewing the mount.

So artifacts now resolve through predict.artifact() under FLAVORMANCER_HOME, which defaults to "."
β€” the existing systemd deployment is byte-for-byte unaffected, and a container can bake the code
in while mounting the data. Verified both directions: unset resolves to the working directory,
set redirects, full suite passes either way.

Docker is not installed on the build box, so the image has NOT been built and run end to end.
The compose file parses and the schema is plain SQL, but the first real `docker compose up`
should be treated as the test. Called out in the PR rather than implied to be verified.

Signed-off-by: Austin L. <86896075+rvnminers-A-and-N@users.noreply.github.com>
@rvnminers-A-and-N rvnminers-A-and-N added area:infra Docker, Compose, Postgres, deploy documentation Improvements or additions to documentation labels Jul 30, 2026
@rvnminers-A-and-N
rvnminers-A-and-N merged commit d8949bb into main Jul 30, 2026
4 checks passed
@rvnminers-A-and-N
rvnminers-A-and-N deleted the feat/packaging-and-v0.2.0 branch July 30, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:infra Docker, Compose, Postgres, deploy documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(infra): Postgres + pgvector container + schema migration feat(infra): Dockerfile per service + docker-compose (single box)

1 participant