"""Experimental rootless Docker bootstrap for Apple-container bottles. The daemon and every child remain inside the existing per-bottle VM. This module deliberately refuses to compensate for missing prerequisites with outer capabilities, a privileged container, or a host Docker socket. """ from __future__ import annotations import shlex import shutil import tempfile import time from pathlib import Path from typing import Callable from ...log import die, info _INIT = "/usr/local/libexec/bot-bottle/rootless-docker-init" _RUNTIME_DIR = "/tmp/bot-bottle-docker-run" _SOCKET = f"{_RUNTIME_DIR}/docker.sock" READY_RETRIES = 30 def build_image( base_image: str, build: Callable[..., None], ) -> str: """Layer spike-only tooling on an already-built provider image.""" image = f"{base_image}-rootless-docker" init_script = Path(__file__).with_name("rootless-docker-init.sh") with tempfile.TemporaryDirectory(prefix="bot-bottle-rootless-docker.") as tmp: context = Path(tmp) shutil.copy2(init_script, context / "rootless-docker-init.sh") (context / "Dockerfile").write_text( "FROM docker:28-cli AS docker_cli\n" f"FROM {base_image}\n" "USER root\n" "COPY --from=docker_cli /usr/local/libexec/docker/cli-plugins/" "docker-compose /usr/local/libexec/docker/cli-plugins/docker-compose\n" "RUN apt-get update \\\n" " && apt-get install -y --no-install-recommends docker.io uidmap " "rootlesskit slirp4netns fuse-overlayfs \\\n" " && rm -rf /var/lib/apt/lists/* \\\n" " && sed -i '/^node:/d' /etc/subuid /etc/subgid \\\n" " && printf 'node:100000:65536\\n' >> /etc/subuid \\\n" " && printf 'node:100000:65536\\n' >> /etc/subgid \\\n" " && ln -s /usr/share/docker.io/contrib/dockerd-rootless.sh " "/usr/local/bin/dockerd-rootless.sh\n" "COPY rootless-docker-init.sh " "/usr/local/libexec/bot-bottle/rootless-docker-init\n" "RUN chmod 0755 /usr/local/libexec/bot-bottle/rootless-docker-init\n" "USER node\n", encoding="utf-8", ) build(image, str(context), dockerfile=str(context / "Dockerfile")) return image def guest_env(enabled: bool) -> dict[str, str]: """Environment consumed by the Docker CLI inside an enabled bottle.""" if not enabled: return {} return { "DOCKER_HOST": f"unix://{_SOCKET}", "XDG_RUNTIME_DIR": _RUNTIME_DIR, } def start(bottle: object) -> None: """Start and verify the unprivileged daemon through the bottle exec API.""" info("starting experimental rootless Docker daemon") result = bottle.exec(shlex.quote(_INIT)) # type: ignore[attr-defined] if result.returncode != 0: detail = (result.stderr or result.stdout or "").strip() die(f"rootless Docker bootstrap failed: {detail or ''}") for _ in range(READY_RETRIES): result = bottle.exec("docker info >/dev/null 2>&1") # type: ignore[attr-defined] if result.returncode == 0: info("rootless Docker daemon is ready") return time.sleep(0.2) logs = bottle.exec( # type: ignore[attr-defined] "tail -n 80 /tmp/bot-bottle-rootless-docker.log 2>/dev/null || true" ) die( "rootless Docker did not become ready without additional outer " f"privileges:\n{(logs.stdout or logs.stderr or '').strip()}" ) __all__ = ["build_image", "guest_env", "start"]