// Package build builds an image from a Dockerfile (RFC 0006): the // base image is resolved through the store, one writable work tree is // created over it, the steps run against that tree, the metadata // instructions go into image.json through store.ApplyChange, and the // result is an ordinary flat werkdock image. // // Everything that depends on the bwrap version lives behind Backend. // The parser, the instructions, COPY, the uid levers, the CLI, and the // commit are the same behind either implementation. package build import ( "werkdock/internal/engine" ) // Backend opens the writable work tree a build's steps run against. // // It is the ONLY part of the build that depends on what bwrap can do. // Two implementations are foreseen (RFC 0006): // // - CopyBackend, the one implemented here, works on the bwrap 0.8 the // Hostsharing webspaces run today: a real full copy of the base // rootfs, bound read-write, committed by renaming the staging // directory. No per-step cache. // - An overlay backend, possible from bwrap 0.9 (Debian 13 brings // 0.11) when bwrap is not installed setuid: `--overlay-src` on the // base, stacked over the upper directories of the steps before it, // `--overlay` on this step's own. Measured to work unprivileged, // and the upper directory is already a layer diff — deletions // appear as character devices 0:0, which is what OCI writes as // `.wh.NAME`. That makes a per-step cache nearly free, which is // why the cache waits for it: without a union mount every cached // step would cost a whole tree copy. // // The copy backend stays after that upgrade — as the fallback for a // bwrap that is too old or setuid, and for single-shot builds, whose // commit is a rename rather than a walk over upper directories. type Backend interface { // Name identifies the backend in build output and in doctor. Name() string // CachesSteps reports whether a step's result can be kept and // reused by a later build. Only an overlay backend can. CachesSteps() bool // Open prepares a work tree over base — an image's rootfs — below // dir, which the caller owns and removes. Open(base, dir string) (Tree, error) } // Tree is one build's writable rootfs. type Tree interface { // Step prepares step n (0-based, in build order). Step(n int) (Step, error) // Commit returns the host path of the finished flat rootfs, which // lies at