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>
50 lines
3.7 KiB
Markdown
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).
|