Add docker CLI and document DooD host setup for CI
Assisted-by: Claude Opus 4.7 (1M context) via Claude Code
change ksqwwwsxuysqyrmplwnvuprnxnlrywwx
commit 7f4d688c93f64358ebd6930a85df5d730a4a89cd
author Alpha Chen <alpha@kejadlen.dev>
date
parent qmkrorml
diff --git a/Dockerfile b/Dockerfile
index 221efe8..ae5bf5a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -71,6 +71,8 @@ RUN apt-get update \
 COPY --from=git-builder /usr/local/bin/git /usr/local/bin/git
 COPY --from=git-builder /usr/local/libexec/git-core/ /usr/local/libexec/git-core/
 COPY --from=builder /build/quire /usr/local/bin/quire
+# CI shells out to docker against the host daemon (DooD); see docs/CI.md.
+COPY --from=docker:cli /usr/local/bin/docker /usr/local/bin/docker
 
 # Configure git hooks globally so all repos inherit the post-receive dispatch.
 # `hook.<label>` is an arbitrary identifier; the hook is bound to an event
diff --git a/docs/host/README.md b/docs/host/README.md
index aae172f..f191de2 100644
--- a/docs/host/README.md
+++ b/docs/host/README.md
@@ -31,14 +31,17 @@ Reference configs for dispatching SSH connections into the quire container.
 
        docker run -d --name quire-container \
            --user "$(id -u git):$(id -g git)" \
+           --group-add "$(getent group docker | cut -d: -f3)" \
            -e HOME=/tmp \
            -v /var/quire:/var/quire \
+           -v /var/run/docker.sock:/var/run/docker.sock \
            -p 127.0.0.1:3000:3000 \
            quire
 
    In a compose file, the equivalent is `user: "${QUIRE_UID}:${QUIRE_GID}"`
    with the values templated from `id -u git` / `id -g git` during host
-   setup.
+   setup, plus `group_add: ["${DOCKER_GID}"]` and the two bind mounts
+   under `volumes:`.
 
    If you want the interim gitweb view, run it as a separate container
    mounting the same volume (read-only is sufficient):
@@ -74,3 +77,29 @@ writable `HOME` for its config probing.
 The HTTP port (3000) is published to host loopback only. A reverse proxy
 on the host terminates TLS and reverse-proxies to it; nothing else
 should reach it directly.
+
+## CI: docker-out-of-docker
+
+The CI runner shells out to docker against the **host** daemon —
+`docker run` to start a per-run container with the pipeline's image,
+`docker exec` for each `(sh ...)` call, `docker stop` at the end.
+Architecture and trade-offs in [docs/CI.md](../CI.md).
+
+For this to work the quire container needs:
+
+- The docker CLI (baked into the image; the host daemon does the work).
+- The host's `/var/run/docker.sock` bind-mounted in.
+- Membership in the host's `docker` group (via `--group-add`) so the
+  unprivileged `git` uid can talk to the socket.
+
+Anyone with the docker socket has root on the host. That's an
+acceptable trade here because quire and the operator account already
+share the box; if that ever stops being true, switch to the OCI+bwrap
+path described in CI.md.
+
+One sharp edge: when quire issues `docker run -v /var/quire/runs/...:/work`,
+the host path is resolved by the host daemon, not interpreted from
+inside the container. So `/var/quire` must resolve to the **same path**
+on the host and inside the quire container. The bind mount above
+(`-v /var/quire:/var/quire`) already enforces this; just don't get
+clever and remap the path on either side.