refactor(orchestrator): split conflated sidecar image into orchestrator + gateway images
One image — `bot-bottle-sidecars:latest`, built from `Dockerfile.sidecars` — served two unrelated roles: the egress/git-gate/supervise *data plane* and the orchestrator *control plane* (which ran the same image with the entrypoint overridden to `python3 -m bot_bottle.orchestrator`). The control plane is stdlib-only, so it needed none of the mitmproxy/git/gitleaks payload it was riding on — while being the most secret-dense process on the host (PRD 0070's "secret concentration"). Split into two purpose-built images: - `Dockerfile.gateway` -> `bot-bottle-gateway:latest` — the data plane (renamed from Dockerfile.sidecars; identical contents). - `Dockerfile.orchestrator` -> `bot-bottle-orchestrator:latest` — a lean `python:3.12-slim` runtime; the bind-mounted `bot_bottle` package supplies the code (so the #381 source-hash recreate semantics are unchanged). `OrchestratorService` now takes distinct `image` (control plane, default `ORCHESTRATOR_IMAGE`) and `gateway_image` (data plane, default `GATEWAY_IMAGE`) instead of feeding one `self.image` to both, and builds the lean image (build-if-missing) before starting the container. The per-bottle bundle constants in `backend/docker/sidecar_bundle.py` now alias the gateway constants so a bundle and the shared gateway can never drift onto different images. The `bot-bottle-sidecars` *image* name and `Dockerfile.sidecars` are gone; the per-bottle *container* name prefix (`bot-bottle-sidecars-<slug>`) is intentionally left for a separate change. Verified end-to-end: both images build; the lean image runs the control plane; `ensure_running` brings up the orchestrator on `bot-bottle-orchestrator:latest` and the gateway on `bot-bottle-gateway:latest` (distinct images) and reports healthy. Closes #384. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
@@ -21,7 +21,7 @@ IMAGE = "busybox"
|
||||
class TestDockerGatewayImageExists(unittest.TestCase):
|
||||
def test_image_exists_true_for_present_false_for_absent(self) -> None:
|
||||
# Ensure the tiny image is present (build_if_missing is disabled here
|
||||
# so this never triggers a Dockerfile.sidecars build).
|
||||
# so this never triggers a Dockerfile.gateway build).
|
||||
subprocess.run(
|
||||
["docker", "pull", IMAGE],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False,
|
||||
|
||||
@@ -6,7 +6,7 @@ config (routes.yaml, etc) — that lands in chunk 2 when the
|
||||
renderer wires the bundle into compose. What we verify here is
|
||||
the chunk-1 contract:
|
||||
|
||||
- Dockerfile.sidecars builds (multi-stage works, base layers
|
||||
- Dockerfile.gateway builds (multi-stage works, base layers
|
||||
pull, COPYs resolve).
|
||||
- gitleaks, mitmdump are at the documented paths and answer
|
||||
`--version`.
|
||||
@@ -28,8 +28,8 @@ import unittest
|
||||
from tests._docker import skip_unless_docker
|
||||
|
||||
|
||||
_IMAGE = "bot-bottle-sidecars-test:chunk1"
|
||||
_DOCKERFILE = "Dockerfile.sidecars"
|
||||
_IMAGE = "bot-bottle-gateway-test:chunk1"
|
||||
_DOCKERFILE = "Dockerfile.gateway"
|
||||
|
||||
|
||||
@skip_unless_docker()
|
||||
|
||||
Reference in New Issue
Block a user