Files
werkdock/README.md
T
Michael HönnigandClaude Opus 5 ccc6176caf chore: eigenes Repository — .werkator.yml und README nach der Herauslösung
Werkdock ist aus dem Werkator-Repository herausgelöst (Plan-Schritt 21,
Sitzung E). Die Historie der neun Commits unterhalb von `werkdock/` bleibt
erhalten (`git subtree split`), die Pfade rücken um das Präfix nach oben.

Die Build-Definition zieht unverändert mit — sie wird hier zur einzigen und
heißt deshalb `default`. Werkator baut Werkdock damit nicht mehr mit; es
konsumiert das Binary über PATH, wie es `git` konsumiert.

Zuhause ist https://git.javagil.de/mi/werkdock; der Gitea-Block der
Konfiguration zeigt dorthin, damit Statusmeldungen am richtigen Commit
landen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 14:40:04 +02:00

3.7 KiB

Werkdock

A docker-like sandbox CLI over bwrap — filesystem isolation only. A dock is the enclosed basin in which ships are built: the dock gate controls what passes, the water outside is shared with the whole harbor. Accordingly, network, uid, /proc, /dev, and /tmp come from the host by contract; that is what makes Werkdock work without root on a Hostsharing Managed Webspace.

Semantics — docker-compatible as far as the filesystem-only contract allows (see RFC 0002):

  • An image is a rootfs archive; an instance is an unpacked, writable directory tree and corresponds to a docker container.
  • werkdock run [flags] IMAGE [CMD...] creates an instance and executes in the sandbox with uid 0 mapped to the calling user; verbs and flags follow docker, unsupported docker flags fail loudly.
  • werkdock doctor checks the host: user-namespace capability, disk and quota headroom.
  • A daemon speaking the Docker Engine API subset (for Testcontainers) is designed for but deferred.

Disk Footprint

Werkdock's storage model is coarser than Docker's on the image side and cheaper on the instance side:

  • An image is a flat, complete directory tree — there are no layers, and nothing is shared between images. A JDK+Go+Node build image is roughly 2 GiB unpacked, plus its compressed archive (~0.5 GiB) as long as that is kept around.
  • An instance costs (almost) nothing: the rootfs is bound read-only into every sandbox, writable are only tmpfs (/tmp, /root) and the caller's binds. Ten parallel runs in one image add zero filesystem copies; what grows per project are its own caches in bound volumes.
  • Consequence: prefer ONE fat image shared by all projects over per-project images.
  • Watch out for orphans: consumers that key an unpacked environment by the archive's source path (Werkator's bwrap runtime does) leave the old tree behind on every path change; pruning is manual until rmi/prune verbs exist.
  • Future options that would remove the flat-tree cost, in their own RFCs when they come due: composable toolchain mounts — a slim base plus per-toolchain prefix binds, no overlayfs needed (RFC 0003, candidate) — overlayfs layers (the kernel allows it unprivileged in a user namespace since 5.11; the webspaces' bwrap 0.8.0 cannot yet), or hardlink deduplication between image versions in the store (the ostree principle, no root needed).

Build and Test

go test ./...                      # all tests; sandbox integration tests skip without bwrap/userns
go vet ./... && gofmt -l .         # quality gates (gofmt must print nothing)
CGO_ENABLED=0 go build .           # one static linux binary, ~3 MB

First steps on a host:

werkdock doctor                    # can this host run sandboxes?
werkdock load -i rootfs.tar.zst    # import a rootfs archive as an image
werkdock run --rm -v /repo:/repo -w /repo IMAGE sh -c './gradlew build'

Status: bootstrap. The implementation language is Go, decided in RFC 0001. Werkdock grew in the werkdock/ subdirectory of the Werkator repository and moved here once it stood on its own (Werkator plan step 21, session E); the history above the split is preserved. It stays self-contained: no imports from Werkator code, no coupling to the Werkator build — Werkator consumes the binary through PATH (bwrap.werkdock), the way it consumes git. Its own CI is the .werkator.yml in this repository; the roadmap that created it is session B of Werkator's plan step 21.