diff --git a/Dockerfile.infra b/Dockerfile.infra deleted file mode 100644 index 0bd1e76e..00000000 --- a/Dockerfile.infra +++ /dev/null @@ -1,22 +0,0 @@ -# Shared infra image: gateway data plane + orchestrator control plane. -# -# Used directly by the Docker backend (run as one `bot-bottle-infra` -# container, replacing the prior two-container split). The Firecracker -# backend extends this via Dockerfile.infra.fc, adding buildah/crun/ -# netavark for in-VM agent-image building. -# -# Dockerfile.orchestrator is the single definition of the orchestrator -# content (the lean `bot_bottle` package on python:3.12-slim). Both this -# image and Dockerfile.infra.fc pull it in via `COPY --from`. -# -# multi-`FROM` can't union two bases (that's multi-stage, not multiple -# inheritance), so the orchestrator content is pulled in via `COPY --from` -# rather than a second base. Both images share the trixie `python:3.12-slim` -# base, so the copy is clean (same python; future installed deps copy too). -FROM bot-bottle-gateway:latest - -# The orchestrator content, from its single definition. The gateway image -# already has the flat daemon modules under /app; this adds the full -# `bot_bottle` package so `python3 -m bot_bottle.orchestrator` resolves — -# used by gateway_init when BOT_BOTTLE_GATEWAY_DAEMONS includes `orchestrator`. -COPY --from=bot-bottle-orchestrator:latest /app/bot_bottle /app/bot_bottle diff --git a/Dockerfile.infra.fc b/Dockerfile.infra.fc index 422fd60c..c2e7dc4f 100644 --- a/Dockerfile.infra.fc +++ b/Dockerfile.infra.fc @@ -1,19 +1,30 @@ # Firecracker infra VM image (PRD 0070 Stage B). # -# Extends the shared infra base (Dockerfile.infra: gateway + orchestrator -# control plane) with the in-VM agent-image builder. The Firecracker backend -# builds users' agent Dockerfiles *inside this VM* with buildah (rootless, -# daemonless) instead of on the host — no host Docker daemon, no -# root-equivalent `docker` group. +# The shared rootfs both firecracker infra VMs boot: the gateway data plane + +# the orchestrator control plane + the in-VM agent-image builder. A `bb_role=` +# kernel-cmdline arg selects which plane the guest init starts (see +# `infra_vm._infra_init`), so there is one artifact to build/publish/pull. # -# Requires the trixie base from bot-bottle-gateway (buildah 1.39: bookworm's -# 1.28 can't parse Dockerfile heredocs that agent images use). +# `Dockerfile.orchestrator` is the single definition of the orchestrator +# content (the lean `bot_bottle` package on trixie `python:3.12-slim`); it's +# pulled in via `COPY --from` (multi-`FROM` can't union two bases). Both images +# share the trixie base, so the copy is clean. # -# `crun` is the OCI runtime; `netavark` + `aardvark-dns` are the network -# backend for `FROM` pulls + `RUN` egress. `vfs` + `chroot`: buildah works -# as root in the bare microVM (no fuse-overlayfs / overlay module / subuid -# maps). Matches image_builder. -FROM bot-bottle-infra:latest +# The Firecracker backend builds users' agent Dockerfiles *inside the +# orchestrator VM* with buildah (rootless, daemonless) instead of on the host — +# no host Docker daemon, no root-equivalent `docker` group. Requires the trixie +# base from bot-bottle-gateway (buildah 1.39: bookworm's 1.28 can't parse the +# Dockerfile heredocs agent images use). `crun` is the OCI runtime; `netavark` + +# `aardvark-dns` are the network backend for `FROM` pulls + `RUN` egress. `vfs` + +# `chroot`: buildah works as root in the bare microVM (no fuse-overlayfs / +# overlay module / subuid maps). Matches image_builder. +FROM bot-bottle-gateway:latest + +# The orchestrator content, from its single definition. The gateway image +# already has the flat daemon modules under /app; this adds the full +# `bot_bottle` package so `python3 -m bot_bottle.orchestrator` resolves in the +# orchestrator-role VM. +COPY --from=bot-bottle-orchestrator:latest /app/bot_bottle /app/bot_bottle RUN apt-get update \ && apt-get install -y --no-install-recommends \ diff --git a/bot_bottle/backend/firecracker/infra_artifact.py b/bot_bottle/backend/firecracker/infra_artifact.py index eb8396df..2d847de5 100644 --- a/bot_bottle/backend/firecracker/infra_artifact.py +++ b/bot_bottle/backend/firecracker/infra_artifact.py @@ -41,7 +41,7 @@ from . import util _ARTIFACT_FORMAT = "1" _REPO_ROOT = Path(__file__).resolve().parents[3] -_DOCKERFILES = ("Dockerfile.orchestrator", "Dockerfile.gateway", "Dockerfile.infra", "Dockerfile.infra.fc") +_DOCKERFILES = ("Dockerfile.orchestrator", "Dockerfile.gateway", "Dockerfile.infra.fc") _DEFAULT_BASE = "https://gitea.dideric.is" _DEFAULT_OWNER = "didericis" diff --git a/bot_bottle/backend/firecracker/infra_vm.py b/bot_bottle/backend/firecracker/infra_vm.py index bca52c81..12e0770e 100644 --- a/bot_bottle/backend/firecracker/infra_vm.py +++ b/bot_bottle/backend/firecracker/infra_vm.py @@ -61,9 +61,10 @@ _GUEST_SIGNING_KEY_PATH = "/var/lib/bot-bottle/orchestrator-token" # the gateway daemons present it to the orchestrator, and never see the key. _GUEST_GATEWAY_JWT_PATH = "/var/lib/bot-bottle/gateway-jwt" -# The single shared infra image: gateway data plane + baked control-plane -# source + buildah (Dockerfile.infra.fc). Built from source by default; a -# pull-from-registry mode lands later. Both VMs boot from it. +# The single shared infra image: gateway data plane + COPY'd control-plane +# `bot_bottle` package + buildah (Dockerfile.infra.fc, FROM gateway). Built from +# source by default; a pull-from-registry mode lands later. Both VMs boot from +# it, the `bb_role` cmdline selecting the plane. _INFRA_IMAGE = "bot-bottle-infra:latest" _GATEWAY_IMAGE = "bot-bottle-gateway:latest" _ORCHESTRATOR_IMAGE = "bot-bottle-orchestrator:latest" @@ -124,9 +125,9 @@ def ensure_built() -> None: Default (docker-free, PRD 0069 Stage 2): download + verify the prebuilt rootfs artifact matching this code version (see `infra_artifact`); the launch host needs no Docker. `BOT_BOTTLE_INFRA_BUILD=local` instead builds - the fixed images from source with host Docker — the infra image - `COPY --from`s the orchestrator image and is `FROM` the gateway image, so - both must exist first — for iterating on the Dockerfiles.""" + the fixed images from source with host Docker — the infra image is `FROM` + the gateway image and `COPY --from`s the orchestrator image, so both must + exist first — for iterating on the Dockerfiles.""" if infra_artifact.local_build_requested(): build_infra_images_with_docker() return @@ -135,17 +136,15 @@ def ensure_built() -> None: def build_infra_images_with_docker() -> None: - """Build the four fixed images from source with host Docker: orchestrator, - gateway, the shared infra base (Dockerfile.infra), then the Firecracker - infra image (Dockerfile.infra.fc: FROM infra + buildah). The launch host - uses this only in `BOT_BOTTLE_INFRA_BUILD=local` mode; `publish_infra` - uses it off-host to produce the published artifact.""" + """Build the three fixed images from source with host Docker: orchestrator, + gateway, then the Firecracker infra image (Dockerfile.infra.fc: FROM gateway + + COPY --from orchestrator + buildah). The launch host uses this only in + `BOT_BOTTLE_INFRA_BUILD=local` mode; `publish_infra` uses it off-host to + produce the published artifact.""" docker_mod.build_image( _ORCHESTRATOR_IMAGE, str(_REPO_ROOT), dockerfile="Dockerfile.orchestrator") docker_mod.build_image( _GATEWAY_IMAGE, str(_REPO_ROOT), dockerfile="Dockerfile.gateway") - docker_mod.build_image( - "bot-bottle-infra:latest", str(_REPO_ROOT), dockerfile="Dockerfile.infra") docker_mod.build_image( _INFRA_IMAGE, str(_REPO_ROOT), dockerfile="Dockerfile.infra.fc")