Skip to content

build(docker): replace pip-install-at-startup with proper Dockerfile (#171)#518

Merged
mvillmow merged 2 commits into
mainfrom
171-proper-dockerfile
May 16, 2026
Merged

build(docker): replace pip-install-at-startup with proper Dockerfile (#171)#518
mvillmow merged 2 commits into
mainfrom
171-proper-dockerfile

Conversation

@mvillmow
Copy link
Copy Markdown
Contributor

Summary

  • New jetstream-consumer/Dockerfile (multi-stage python:3.12-slim, non-root UID/GID 1000, embedded HEALTHCHECK /health) bakes nats-py==2.9.0 at build time instead of running pip install nats-py on every container start.
  • docker-compose.yml now build:s from ./jetstream-consumer and accepts a JETSTREAM_CONSUMER_IMAGE override (documented in .env.example) so production can pin a published GHCR tag.
  • New .github/workflows/publish-jetstream-consumer-image.yml publishes multi-arch GHCR images on main, mirroring the existing exporter pipeline.
  • tests/test_dockerfile_constraints.py extended to guard both Dockerfiles' Python base version.

pip install uses -r /tmp/requirements.txt (stdin-style — not the repr()-wrapped form that caused breakage on HI Hermes). tini and other base-image-moving packages are intentionally not pinned.

Closes #171

Test plan

  • CI green (Lint Python, Test exporter, yamllint, env-example drift check).
  • docker compose build jetstream-consumer succeeds locally.
  • docker compose up -d jetstream-consumer reaches healthy without 10s startup pip-install delay.
  • curl http://localhost:9101/metrics returns Prometheus output.

Generated with Claude Code

@mvillmow mvillmow enabled auto-merge (squash) May 14, 2026 03:02
mvillmow and others added 2 commits May 15, 2026 18:55
…171)

The jetstream-consumer service was running
`sh -c "pip install nats-py -q && python /consumer.py"` as its compose
command, which re-downloaded nats-py on every container restart, added
~10s of startup latency, and broke entirely in air-gapped environments.

This change introduces a real `jetstream-consumer/Dockerfile` that bakes
the pinned dependency at build time (mirroring `exporter/Dockerfile`):
multi-stage `python:3.12-slim` base, non-root UID/GID 1000, embedded
`HEALTHCHECK` against `/health`, and a stdin-style
`pip install -r /tmp/requirements.txt` to avoid `repr()`-quoting bugs
from prior HI Hermes Dockerfiles. Dependencies are pinned in
`jetstream-consumer/requirements.txt` (nats-py==2.9.0) and tini is
deliberately not pinned (it ships with the base image).

docker-compose.yml now `build:`s from `./jetstream-consumer` and lets
operators pin a published GHCR tag via `JETSTREAM_CONSUMER_IMAGE` (new
optional override documented in `.env.example`). A new
`publish-jetstream-consumer-image.yml` workflow publishes multi-arch
images to GHCR on every main-branch change to `jetstream-consumer/**`,
matching the pattern established for `argus-exporter`. The static
`test_dockerfile_constraints.py` regression test now also guards the
new Dockerfile's Python base version.

Closes #171

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The image format validator failed on
${JETSTREAM_CONSUMER_IMAGE:-argus-jetstream-consumer:local} because the
literal ${...:-...} pattern did not match the image-name regex.

Substitute compose env-var interpolations of the form ${VAR:-default}
and ${VAR-default} with their default value before regex validation.
Bare ${VAR} (no default) is skipped since we cannot validate without
a runtime value.
@mvillmow mvillmow force-pushed the 171-proper-dockerfile branch from 09761ee to 393ee9a Compare May 16, 2026 08:36
@mvillmow mvillmow merged commit 9a0ee49 into main May 16, 2026
20 checks passed
@mvillmow mvillmow deleted the 171-proper-dockerfile branch May 16, 2026 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace pip-install-at-startup pattern with a proper Dockerfile

1 participant