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

50 lines
3.7 KiB
Markdown

# 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](docs/rfcs/0002-docker-compatible-surface.md)):
- 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](docs/rfcs/0003-composable-toolchain-mounts.md), 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
```bash
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:
```bash
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](docs/rfcs/0001-implementation-language.md).
Werkdock grew in the `werkdock/` subdirectory of the [Werkator](https://github.com/mhoennig/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](https://github.com/mhoennig/werkator/blob/main/docs/plan/21-werkdock-extraction-and-webspace-install.md).