ossein-docker: a docker-shaped front for build, run, pull, stop - #10
Merged
Conversation
closer-claudio
force-pushed
the
claudio/20260907-ossein-docker
branch
from
September 7, 2026 07:35
89e0139 to
e5d3149
Compare
closer-claudio
force-pushed
the
claudio/20260907-ossein-docker
branch
from
September 13, 2026 18:06
e5d3149 to
a8d0b24
Compare
This was referenced Sep 13, 2026
closer-claudio
force-pushed
the
claudio/20260907-ossein-docker
branch
3 times, most recently
from
September 14, 2026 05:28
730bc3b to
7484428
Compare
Every buildkit instance now records what it serves (buildkit.json in its state dir: the cache directory it holds and its host socket), and `ossein buildkit --detach` for a cache that a live instance already serves reprints that instance's BUILDKIT_HOST and exits 0 instead of failing on the lock. A still-booting instance is waited for, never killed: it is not ours. The foreground path and an explicit --sock are unchanged. image.Import records a locally built image (an OCI layout produced by a build) under a tag, exactly as a registry resolution would be, so a later `ossein run <tag>` resolves offline under the default pull policy. Such a resolution is marked local: when its rootfs blob is reclaimed, the error asks for a rebuild instead of re-fetching a digest no registry has. One builder, newResolution, now produces the record for Resolve and Import alike — digest and config derived from the image's own bytes, the manifest chain kept — so an imported tag carries the same record shape as a pulled one, and Resolve's Image is built from the record it just wrote rather than from a second reading of the same image. A record Resolve fails to write is logged, not swallowed; Import's is checked, as before. `--cpus 0` and `--memory 0` on run and buildkit now mean the whole host: every logical CPU and all physical memory, each capped at what Virtualization.framework allows for one guest (pkg/vm HostMaxCPUs and HostMaxMemoryMiB). 0 is docker's own spelling of "no limit", and it is what the docker-shaped front passes when a script sizes nothing — a container under a daemon gets the machine, and so does one under the front. The framework's maximum is not the host's (64 CPUs on an 18-core machine), which is why the cap is the host's count and not the framework's. ossein's own defaults (2 vCPU / 4 GiB, 4 / 8 GiB for buildkit) are untouched; 0 was never a usable value before. Drive-by: kong splits repeated flag values on commas by default, so `-e LIST=a,b` arrived as two variables. sep:"none" on -e, --env-file, -v. What the two binaries must agree on moves to internal/cli: the process logger, the --log-level vocabulary, the exit-status convention, and the spelling of "the whole host" (cli.WholeHost) — named for what it holds, the conventions of the product's command-line binaries, not for who calls it. kong's `var cli CLI` in each main becomes `root` so the package is never shadowed at the one place it is used. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: closer-claudio <claudio@farcloser.world>
cmd/ossein-docker implements the docker invocations farcloser projects actually make, with the flags they actually pass (surveyed: build-curl's build-posix.sh, the bench scripts, the website copy), and refuses everything else loudly: an unknown flag or subcommand is a parse error, never a silent no-op. Where docker and ossein disagree, docker wins. - run, pull, stop: exec the sibling ossein binary (its flags are already docker-shaped); docker's resource syntax is translated — --cpus 1.5 rounds up, --memory takes docker's grammar (8g, 8gb, 512MiB, 1.5g) — and --network none becomes --no-network. -it, commas in -e, -- before the image. A run that sizes nothing is sized like a docker container: the whole host (cli.WholeHost on both knobs), not ossein's defaults. stop requires an id, as docker requires a container: a bare stop would stop every builder on the machine, which docker never does. - build (and buildx build): the buildkit client library, not buildctl. Starts or reuses this directory's buildkit microVM via `ossein buildkit --detach`, sized like a daemon (the whole host); solves with the dockerfile.v0 frontend (context and Dockerfile as local mounts; -t -f --build-arg --platform --target --no-cache --pull --progress -q); exports an OCI layout and imports every -t tag into ossein's image cache through image.Import, flattened right away — `docker run <tag>` then resolves offline. -q without -t is refused: docker would print an image ID, but an untagged build leaves ossein nothing runnable to name, and printing nothing would be exactly the silent divergence this front exists to refuse. - registry credentials for FROM lines: a Credentials-only session attachable backed by go-containerregistry's default keychain (docker login), instead of buildkit's authprovider, which would have pulled docker/cli and an MPL-2.0 HTTP helper into the binary. Release: a second goreleaser build in the same archive (no entitlement: the front never touches Virtualization itself). go-licenses cannot locate the Apache-2.0 license of the two in-toto modules the client pulls (module-layout false positive, google/go-licenses#186): ignored in the Justfile with the reason. go.mod carries the three direct dependencies, tidied on main. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: closer-claudio <claudio@farcloser.world>
closer-claudio
force-pushed
the
claudio/20260907-ossein-docker
branch
from
September 14, 2026 05:30
7484428 to
152652f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
cmd/ossein-docker: a docker-shaped front for thedockerinvocations farcloser projects actually make —build,run,pull,stop,version— with the flags they actually pass (surveyed: forkcloser/curl'sbuild-posix.sh, the bench scripts, the website copy). Anything else is refused loudly (unknown flag/subcommand is an error, never a silent no-op). Meant to be installed asdockeron the hermetic PATH (aqua packaging follows in limen once a release carries both binaries). Where docker and ossein disagree, docker wins.What it does
execveinto the siblingossein(flags already docker-shaped). Translates docker's--cpus 1.5(rounded up),--memoryin docker's grammar (8g,8gb,512MiB,1.5g),--network none; keeps-it, commas in-e, puts--before the image. A run that sizes nothing gets the whole host (every CPU, all memory — backed lazily), as a docker container does;ossein run's own 2 vCPU / 4 GiB do not apply through the front.stoprequires an id, as docker requires a container: a barestopwould have stopped every builder on the machine, which docker never does.v0.32.0, same as the daemon image), notbuildctl. Starts or reuses this directory's buildkit microVM viaossein buildkit --detach, sized like a daemon (the whole host); solves withdockerfile.v0(context + Dockerfile as local mounts;-t -f --build-arg --platform --target --no-cache --pull --progress -q); exports an OCI layout and imports every-ttag into ossein's image cache, flattened right away — sodocker run <tag>resolves offline.-qwithout-tis refused: docker would print an image ID, but an untagged build leaves ossein nothing runnable to name, and printing nothing would be the silent divergence this front exists to refuse.FROM: aCredentials-only session attachable backed by go-containerregistry's default keychain (docker login). Not buildkit'sauthprovider, which would have pulleddocker/cliand an MPL-2.0 HTTP helper (rejected by the license lane).ossein-side changes (first commit)
ossein buildkit --detachis now idempotent per cache: each instance recordsbuildkit.json(cache dir + socket) in its state dir; a second detach for a cache a live instance serves reprints itsBUILDKIT_HOSTand exits 0 instead of failing on the lock. A booting instance is waited for, never killed. Foreground and explicit--sockunchanged.--cpus 0/--memory 0onrunandbuildkitmean the whole host: the host's logical CPU count and physical memory, each capped at what Virtualization.framework allows for one guest (vm.HostMaxCPUs,vm.HostMaxMemoryMiB). The framework's own maximum is not the host's (64 CPUs on an 18-core machine), hence the cap on the host's count. 0 is docker's spelling of "no limit" and is what the front passes; ossein's defaults are untouched.image.Import: records a locally built image under a tag exactly like a registry resolution; markedlocalso a reclaimed blob says "rebuild" rather than re-fetching a digest no registry has.ossein run -e LIST=a,barrived as two variables.sep:"none"on-e,--env-file,-v.internal/cli: the logger, the--log-levelvocabulary, the exit convention, andcli.WholeHost— the one definition of "0 = the whole host" both sides use. One record builder,newResolution, servesResolveandImport; an imported tag now carries the same manifest chain as a pulled one, and a recordResolvefails to write is logged, not swallowed.Release / lint
ossein-docker) in the same archive, no entitlement (it never touches Virtualization itself).LICENSEfile in repo root is ignored google/go-licenses#186):--ignored in the Justfile with the reason; both licenses read from the module cache.tools/→hack/, tool directives intools/go.mod) and onto image: write the resolution record durably #14 and image: a digest-pinned ref only trusts a record that hashes back to it #13: the resolution record keeps its manifest chain and is written durably;Importrecords carry thelocalflag on top of that and write through the same path, checked.go.modcarries the three direct dependencies, tidied on main.Verification
just lintandjust testgreen locally. Unit tests cover argv translation (including the whole-host default and docker's memory grammar), frontend attrs, tag normalization, OCI-layout selection (attestations skipped, platform matched, nested-index errors not masked),Import→ offlineResolve→ cached rootfs, instance discovery, the-q-without--tand bare-stoprefusals.build/dockersymlinked toossein-docker:docker build --build-arg GREETING=hi -t smoke:dev .→ alpine pulled through the builder,RUNexecuted, tag imported;docker run --rm smoke:devprinted the build-arg'd file offline.docker run: guest sawnproc=18, 64 GiB;--cpus 1.5 --memory 1gb:nproc=2, 1 GiB.-e LIST=a,barrived intact;docker build -q .refused (125) with the message;-q -tprinted the digest only;buildx buildworks; secondossein buildkit --detachsaidreusing; baredocker stoprefused;docker stop <id>stopped only that one.build-posix.sh(Forkcloser session), adapted todocker run …on macOS; its linux-arm64/amd64 legs will be run against this branch'sjust buildoutput.