crane append: Add a Layer Without a Dockerfile
crane append lays a tarball on top of a base image as a new layer and pushes the resulting image, with no Dockerfile and no daemon.
For images that are just "a base plus a few files" (a static binary, some config) crane append builds them without a Dockerfile or a builder, which is fast and reproducible in CI.
What it does
crane append takes a base image (-b) and one or more layer tarballs (-f), creates a new image with those layers on top, and either pushes it to a tag (-t) or writes it to a tarball (-o). It is a minimal, deterministic way to produce an image from files.
Common usage
# pack a binary into a tar, then append it onto a base
tar -cf app-layer.tar -C ./dist app
crane append \
-b gcr.io/distroless/static:nonroot \
-f app-layer.tar \
-t ghcr.io/acme/app:1.4.0
# write the result to a local tarball instead of pushing
crane append -b alpine:3.20 -f app-layer.tar -o image.tarOptions
| Flag | What it does |
|---|---|
| -b, --base <ref> | Base image to append onto |
| -f, --new_layer <tar> | Tarball to add as a new layer (repeatable) |
| -t, --new_tag <ref> | Push the result to this reference |
| -o, --output <file> | Write the result to a tarball instead of pushing |
| --insecure | Allow HTTP / skip TLS verification |
In CI
crane append is ideal for a static Go/Rust binary on a distroless base: build the binary, tar it, append it, and push, all without a Docker daemon or BuildKit. Because the inputs are fixed the output digest is stable across runs.
Common errors in CI
"UNAUTHORIZED: authentication required" pushing to -t means log in first. A layer that lands in the wrong place usually means the tar was created without the right -C base directory (paths inside the tar become paths inside the image). "MANIFEST_UNKNOWN" on -b means the base reference is wrong.