Files
bot-bottle/docs/image-build-inputs.md
T

3.5 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 are required, defaultless Docker build arguments. Their version-qualified tags and multi-platform OCI index digests live together in image-build-args.json; every supported builder reads that file and passes only the arguments its Dockerfile declares.
  • 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 update its one digest-pinned value in image-build-args.json. 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.