c60e6b7e9f
Addresses the review finding that buildah lived only in the orchestrator
image, so the persistent infra VM wasn't the builder — a separate throwaway
builder VM contended with it for the orchestrator TAP. Consolidate:
- **Rebase the gateway (and thus infra) on `python:3.12-slim` = Debian
trixie**, pip-installing mitmproxy instead of `FROM mitmproxy/mitmproxy`
(Debian bookworm). trixie ships buildah 1.39, which can build agent
Dockerfiles that use heredocs; bookworm's 1.28 can't (`Unknown
instruction: "{"`). CA path is unchanged (set via `--set confdir=`).
- **buildah lives only in `Dockerfile.infra`** now (removed from the
orchestrator image, which is lean/stdlib-only again).
- **Shared orchestrator content**: `Dockerfile.orchestrator` is the single
definition of the control-plane payload; the infra image `COPY --from`s
it (same trixie base → clean copy, and future deps like iroh are added
once). The docker backend runs the orchestrator image directly.
- **`image_builder` builds inside the infra VM** (which now has buildah)
over SSH — no throwaway builder VM, so the `bborch0` contention is gone.
`ensure_built` builds orchestrator + gateway before infra (FROM gateway,
COPY --from orchestrator).
Verified on a KVM host: images build (buildah 1.39 in infra), the agent
image builds *inside* the infra VM (heredoc Dockerfile and all), the infra
VM stays healthy, the agent boots and `claude --version` = 2.1.172. The
rebased gateway still starts as a docker container and generates its CA
(docker backend unaffected).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
117 lines
5.5 KiB
Docker
117 lines
5.5 KiB
Docker
# Gateway data-plane image (PRD 0024 bundle shape; PRD 0070 gateway).
|
|
#
|
|
# The egress / git-gate / supervise *data plane* — one image, run by
|
|
# the consolidated per-host gateway (PRD 0070). It is NOT the
|
|
# orchestrator control plane: that is the separate, lean
|
|
# `bot-bottle-orchestrator` image (Dockerfile.orchestrator, #384), which
|
|
# ships only python + the stdlib-only `bot_bottle` package and none of
|
|
# this image's mitmproxy / git / gitleaks payload.
|
|
#
|
|
# Collapses the prior per-daemon images (egress, git-gate,
|
|
# supervise) into one. A small stdlib-Python init supervisor at
|
|
# /app/gateway_init.py spawns all daemons, forwards SIGTERM, and
|
|
# propagates per-daemon stdout/stderr to the container log with a
|
|
# `[name]` prefix. See PRD 0024 for the rationale.
|
|
#
|
|
# Layout:
|
|
#
|
|
# /usr/bin/gitleaks gitleaks binary
|
|
# /app/egress_addon.py + siblings mitmproxy addon (egress)
|
|
# /app/egress-entrypoint.sh mitmdump launcher
|
|
# /app/supervise_server.py + .py supervise MCP server
|
|
# /app/gateway_init.py PID 1 supervisor
|
|
# /etc/egress/routes.yaml bind-mounted at run time
|
|
# /etc/git-gate/pre-receive docker-cp'd at start time
|
|
# /git-gate-entrypoint.sh docker-cp'd at start time
|
|
# /git-gate/creds/* docker-cp'd at start time
|
|
# /git/* bare repos, populated at runtime
|
|
# /run/supervise/bot-bottle.db bind-mounted at run time
|
|
# /home/mitmproxy/.mitmproxy/ mitmproxy CA dir
|
|
#
|
|
# Exposed ports inside the container:
|
|
# 9099 egress (mitmproxy, agent-facing HTTPS proxy)
|
|
# 9418 git-gate (git-daemon)
|
|
# 9420 git-gate smart HTTP (VM-backend agent-facing transport)
|
|
# 9100 supervise (MCP HTTP)
|
|
|
|
# Stage 1: gitleaks binary. The upstream gitleaks image is alpine
|
|
# with the binary at /usr/bin/gitleaks. Pinned by digest in lockstep
|
|
# with Dockerfile.git-gate's prior base (now deleted at chunk 3).
|
|
FROM zricethezav/gitleaks@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f AS gitleaks-src
|
|
|
|
# Stage 2: assembly. Based on `python:3.12-slim` (Debian trixie) rather
|
|
# than the `mitmproxy/mitmproxy` image (Debian bookworm) so the whole
|
|
# stack — gateway here, and the firecracker infra image that builds
|
|
# FROM this — lands on trixie, whose buildah (1.39) can build agent
|
|
# Dockerfiles that use heredocs. mitmproxy is pip-installed to the same
|
|
# effect as the upstream image. (bookworm's buildah is 1.28, which can't
|
|
# parse `RUN ... <<EOF`; see the infra image + PR discussion.)
|
|
FROM python:3.12-slim
|
|
|
|
# Runtime system deps:
|
|
# git supplies the `git daemon` subcommand (no separate package)
|
|
# plus the core `git` binary the pre-receive hook invokes.
|
|
# openssh-client supplies the upstream SSH transport the
|
|
# pre-receive hook uses to forward accepted refs.
|
|
# ca-certificates is needed for mitmdump upstream TLS.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends \
|
|
git openssh-client ca-certificates \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# mitmdump (the egress data plane). The upstream mitmproxy image baked
|
|
# this in; on the plain python base we pip-install the same pinned
|
|
# version. Its CA dir is set explicitly via `--set confdir=` in
|
|
# egress-entrypoint.sh, so it doesn't depend on a `mitmproxy` home user.
|
|
RUN pip install --no-cache-dir mitmproxy==11.1.3
|
|
|
|
# Pull the standalone binaries into the final image.
|
|
COPY --from=gitleaks-src /usr/bin/gitleaks /usr/bin/gitleaks
|
|
|
|
# Project Python: addon + server modules + the init supervisor.
|
|
# Kept flat under /app/ so mitmdump's loader resolves them as
|
|
# top-level siblings (absolute imports), matching the prior
|
|
# Dockerfile.egress / Dockerfile.supervise layout.
|
|
COPY bot_bottle/egress_addon_core.py /app/egress_addon_core.py
|
|
COPY bot_bottle/egress_dlp_config.py /app/egress_dlp_config.py
|
|
COPY bot_bottle/egress_addon.py /app/egress_addon.py
|
|
COPY bot_bottle/policy_resolver.py /app/policy_resolver.py
|
|
COPY bot_bottle/dlp_detectors.py /app/dlp_detectors.py
|
|
COPY bot_bottle/yaml_subset.py /app/yaml_subset.py
|
|
COPY bot_bottle/paths.py /app/paths.py
|
|
COPY bot_bottle/migrations.py /app/migrations.py
|
|
COPY bot_bottle/db_store.py /app/db_store.py
|
|
COPY bot_bottle/supervise_types.py /app/supervise_types.py
|
|
COPY bot_bottle/queue_store.py /app/queue_store.py
|
|
COPY bot_bottle/audit_store.py /app/audit_store.py
|
|
COPY bot_bottle/store_manager.py /app/store_manager.py
|
|
COPY bot_bottle/supervise.py /app/supervise.py
|
|
COPY bot_bottle/supervise_server.py /app/supervise_server.py
|
|
COPY bot_bottle/gateway_init.py /app/gateway_init.py
|
|
COPY bot_bottle/git_http_backend.py /app/git_http_backend.py
|
|
COPY bot_bottle/egress_entrypoint.sh /app/egress-entrypoint.sh
|
|
RUN chmod +x /app/egress-entrypoint.sh
|
|
|
|
# Pre-create runtime directories the compose renderer + start
|
|
# step expect to exist. `docker cp` does not create intermediate
|
|
# dirs, and bind mounts won't either if the parent is missing.
|
|
RUN mkdir -p \
|
|
/etc/egress \
|
|
/etc/git-gate \
|
|
/git-gate/creds \
|
|
/git \
|
|
/run/supervise \
|
|
/home/mitmproxy/.mitmproxy
|
|
|
|
# Documentation only — the compose renderer publishes whichever
|
|
# subset the bottle uses.
|
|
EXPOSE 8888 9099 9418 9420 9100
|
|
|
|
# WORKDIR matches Dockerfile.supervise's prior layout so the
|
|
# in-app same-dir import in supervise_server.py stays deterministic.
|
|
WORKDIR /app
|
|
|
|
# PID 1 is the supervisor. It owns signal handling and exit-code
|
|
# propagation; no `exec` chain in the entrypoint itself.
|
|
ENTRYPOINT ["python3", "/app/gateway_init.py"]
|