Files
bot-bottle/docs/image-build-inputs.md
T
didericis-codex 377f8d125b
prd-number-check / require-numbered-prds (pull_request) Successful in 8s
refresh-image-locks / refresh (push) Successful in 28s
lint / lint (push) Successful in 1m3s
test / unit (pull_request) Successful in 53s
test / integration-docker (pull_request) Successful in 2m50s
test / coverage (pull_request) Failing after 22s
test / image-input-builds (pull_request) Successful in 3m35s
tracker-policy-pr / check-pr (pull_request) Failing after 11m8s
build: make pinned image inputs portable
2026-07-26 09:42:54 +00:00

3.3 KiB

Container image build inputs

Bot-bottle's supported images are intended to rebuild from the same declared inputs on Linux amd64 and arm64. The repository enforces four layers of immutability:

  • Python and Node base images use version-qualified tags plus multi-platform OCI index digests.
  • Debian packages resolve from the same dated snapshot.debian.org archive in every image that runs apt-get install. The snapshot endpoint uses HTTP so a fresh image does not need a host-specific TLS interception CA; APT still authenticates the repository metadata and package hashes with Debian's signed Release files.
  • Gateway Python dependencies install from requirements.gateway.lock with pip --require-hashes; provider npm packages install with npm ci from committed lockfiles.
  • The Codex standalone installer is fetched from the selected Codex release tag, checked against install.sh.sha256, invoked with an exact --release, and then verifies the selected release archive against upstream metadata. The standalone layout is retained because Codex remote control requires it.

Dockerfile.orchestrator.fc is the one intentionally dynamic FROM. It has no default value: the Firecracker build coordinator resolves the freshly built orchestrator's local sha256: image ID, creates a local tag containing the complete ID, verifies that tag resolves to the same ID, and supplies the content-derived reference as ORCHESTRATOR_BASE_IMAGE. This accommodates BuildKit, which treats a bare image ID in FROM as a registry repository.

Refreshing inputs

Make refreshes on a feature branch and review them like an application dependency update:

  1. For a Python or Node base update, select a version-qualified tag and record its multi-platform index digest in every Dockerfile that shares the base. Confirm the index still contains linux/amd64 and linux/arm64.
  2. For Debian packages, advance DEBIAN_SNAPSHOT to one fixed UTC timestamp in every Dockerfile that uses apt. Do not use the moving Debian mirrors.
  3. Change direct Python versions in requirements.gateway.in, direct npm versions in the provider's package.json, or CODEX_VERSION in the Codex Dockerfile. Direct versions must be exact—no ranges, dist-tags, or unversioned package names.
  4. Push the feature branch or manually run the refresh-image-locks workflow. It regenerates the four derived files with the image's exact Python and Node versions and uploads them as the image-input-locks artifact. It never writes to the branch, so a refresh cannot race with developer pushes.
  5. Download the artifact, replace the four committed files, review the lock diff, and let both normal CI and image-input-builds pass. The latter checks both base architectures, builds every supported image, exercises the exact local Firecracker base-ID handoff, and runs each provider CLI's version smoke test.

Run the fast policy check locally at any point:

python3 scripts/check_image_inputs.py

The check rejects mutable or latest bases, moving apt repositories, network-to-shell installers, unlocked npm/Pi installs, non-exact direct dependencies, missing npm integrity values, and unhashed gateway Python requirements.

Image signing and attestation are tracked separately in issue #339; this policy covers deterministic and integrity-checked build inputs.