Files
werkdock/internal/cli/load.go
mhoennigandClaude Fable 5.1 05bb4e7ae5 load: docker save and OCI image archives, layers flattened (RFC 0004)
werkdock load -i ARCHIVE reads the docker save manifest (legacy and
OCI layout) or a plain OCI image layout, applies the layers in order
into one rootfs with whiteout handling, and keeps the OCI config as
the image metadata. Layer extraction is werkdock's own: every path is
resolved inside the rootfs the way the sandbox sees it, following
lower layers' symlinks and clamping .. at the root as a chroot does,
so a hostile layer can rewrite the image but never the host. gzip
layers in-process, zstd through the zstd binary. RepoTags name the
image, each further tag is a hardlinked copy; a multi-arch index picks
the host platform, otherwise the available ones are listed.

Verified against docker 27 save archives of busybox:1.36 and
alpine:3.20, run in the sandbox afterwards.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-05 23:09:41 +02:00

50 lines
1.3 KiB
Go

package cli
import (
"errors"
"flag"
"fmt"
"io"
"os"
"werkdock/internal/store"
)
// loadCmd is `docker load`: a `docker save` archive or an OCI image
// layout into the store, layers flattened, metadata kept (RFC 0004).
// --name still routes a plain rootfs archive to import, for the callers
// that predate `werkdock import` (Werkator), with a note.
func loadCmd(args []string) int {
fs := flag.NewFlagSet("load", flag.ContinueOnError)
fs.SetOutput(io.Discard)
var input, name string
fs.StringVar(&input, "i", "", "image archive to load")
fs.StringVar(&input, "input", "", "image archive to load")
fs.StringVar(&name, "name", "", "image reference for a rootfs archive (deprecated; use werkdock import)")
if err := fs.Parse(args); err != nil {
return fail(err)
}
if input == "" {
return fail(errors.New("load needs -i ARCHIVE"))
}
if len(fs.Args()) != 0 {
return fail(fmt.Errorf("unexpected argument %q", fs.Args()[0]))
}
if name != "" {
fmt.Fprintf(os.Stderr, "werkdock: load --name imports a rootfs archive; prefer: werkdock import %s %s\n", input, name)
return importArchive(input, name, store.ImageConfig{})
}
st, err := store.Default()
if err != nil {
return fail(err)
}
loaded, err := st.Load(input, "")
if err != nil {
return fail(err)
}
for _, ref := range loaded {
fmt.Printf("Loaded image: %s\n", ref)
}
return 0
}