Skip to content

feat(docker): slim multi-stage image, variant A: base-image python - #369

Open
jp-fizzbee wants to merge 1 commit into
mainfrom
user/jp/feat-docker-slim-image
Open

feat(docker): slim multi-stage image, variant A: base-image python#369
jp-fizzbee wants to merge 1 commit into
mainfrom
user/jp/feat-docker-slim-image

Conversation

@jp-fizzbee

@jp-fizzbee jp-fizzbee commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Variant A of two — see PR for user/jp/feat-docker-hermetic-python (variant B) for the alternative; the two are mutually exclusive, pick one. Both replace the abandoned single-stage image (full bazel/Ubuntu/JDK build env, gigabytes of unpatched CVE surface).

A (this PR) B (hermetic)
Parser's python Base image's (python:3.12-slim) via symlink rules_python bundled interpreter, as tarballs ship
Size 308MB 525MB
Interpreter CVE patching docker pull after base rebuild Only via bazel toolchain pin bump + republish
Risk Relies on rules_python runfiles layout (unstable interface); mitigated by pre-push smoke tests on both arches None beyond status quo

Review-feedback changes since the first revision

  • \|\| true removed entirely — the rules_python 1.9.2 bump is dropped (see below), so no venv exists; a defensive documented rm -rf guards future bumps.
  • rules_python bump withdrawn: 1.9.2's venv-based bootstrap is broken for cross-compiled binaries (stub disables the venv, no baked imports → ModuleNotFoundError at runtime). It would have broken release tarballs for every cross-built platform. Needs separate investigation.
  • mbt_gen.zip includedfizz mbt-scaffold works in the container (smoke-tested).
  • Builder pinned to gcr.io/bazel-public/bazel:8.3.1.
  • Smoke tests expanded: amd64 runs Counter + two-phase-commit (exercises antlr4/protobuf parser surface) + mbt-scaffold; arm64 runs Counter under QEMU before any push. PASSED-grep is the real assertion (binary exits 0 even on FAILED — exit code alone is insufficient by design).
  • Post-push manifest verification (both architectures present).
  • latest tag policy documented in the workflow header (moves on version tags AND monthly rebuilds).
  • Packaging divergence from build_release.sh documented in the Dockerfile header.

Verification

  • Local (arm64): image assembled via the exact Dockerfile commands runs two-phase-commit with baseline-identical output (331/281) on the base image's interpreter; scaffold works; relative spec paths work.
  • docker scout: only 4 perl CVEs remain — currently unfixed upstream in every Debian release, present in the bare python:slim base too; they clear via the monthly rebuild once Debian ships fixes.
  • Builder stage in-container: covered by the workflow's pre-push smoke tests (needs amd64; first workflow_dispatch after merge exercises it).

Post-merge checklist

  1. Actions → Docker → Run workflow (no tag needed).
  2. Verify smoke tests green; manifest shows both platforms.
  3. Make the ghcr package public (first publish defaults to private).

🤖 Generated with Claude Code

…sh workflow

The published Docker image was the single-stage build environment: the
full bazel/Ubuntu/JDK base with the source tree copied in — gigabytes
of CVE surface that no base-image update could fix, reported by users
wanting to run fizzbee in CI.

Dockerfile (rewritten multi-stage):

- Builder stage on gcr.io/bazel-public/bazel:8.3.1 (version-pinned for
  reproducibility), amd64-pinned (the bazel base has no arm64 manifest),
  cross-compiling per TARGETARCH via bazel --platforms — the same
  mechanism release/build_release.sh uses.
- Runtime stage is python:3.12-slim + the release artifacts (including
  mbt_gen.zip, so `fizz mbt-scaffold` works in the container), with NO
  RUN steps — buildx multi-arch needs no QEMU for the build.
- The one deliberate divergence from the tarball layout (documented in
  the file header): the bundled rules_python hermetic interpreter — a
  93MB unstripped binary that cp -L materializes 3x, plus 89MB
  libpython, ~390MB total — is replaced with a symlink to the base
  image's python. Interpreter CVE fixes then flow in via base-image
  rebuilds instead of waiting on a bazel pin bump. The base is
  minor-pinned (3.12) so stdlib behavior can't silently jump.

Result: 308MB (from multi-GB), scanner-clean except 4 perl CVEs that
are currently unfixed upstream in every Debian release (present in the
bare python:slim base as well; they clear via the scheduled rebuild
once Debian ships fixes).

An alternative variant that keeps the hermetic bazel interpreter
(conventional rules_python packaging, ~525MB) is maintained on the
feat-docker-hermetic-python branch for comparison.

.github/workflows/docker.yaml (new):

- Publishes ghcr.io/<repo> on v* tags (semver + latest), monthly cron
  (refreshes base-image patches into `latest` without a release), and
  manual dispatch. Tag policy documented in the workflow header.
- Pre-push smoke tests on BOTH architectures: amd64 runs Counter +
  two-phase-commit (the latter exercises the parser's antlr4/protobuf
  surface) + mbt-scaffold; arm64 runs Counter under QEMU. The PASSED
  grep is the real assertion — the binary exits 0 even on FAILED.
- Post-push: imagetools inspect verifies the manifest lists both
  architectures.

NOT included (deliberately): the rules_python 1.0.0 -> 1.9.x bump
explored during development. 1.9.2's venv-based bootstrap is broken
for cross-compiled binaries (the stub disables the venv and bakes no
import paths -> ModuleNotFoundError at runtime), which would break the
release tarballs for every cross-built platform. Needs its own
investigation; the defensive _parser_bin.venv rm -rf in the Dockerfile
guards against a future bump reintroducing the artifact.

Verified locally (arm64): image assembled from cross-compiled artifacts
via the exact Dockerfile commands runs two-phase-commit with
baseline-identical output (331/281) on the base image's interpreter,
and mbt-scaffold works.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jp-fizzbee
jp-fizzbee force-pushed the user/jp/feat-docker-slim-image branch from 1e77a62 to e8d0554 Compare August 18, 2026 21:21
@jp-fizzbee jp-fizzbee changed the title feat(docker): slim multi-stage image + ghcr publish workflow + rules_python bump feat(docker): slim multi-stage image, variant A: base-image python Aug 18, 2026
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.

2 participants