manifest-tool: Assemble Multi-Arch Manifest Lists
manifest-tool builds a multi-arch manifest list from separately pushed per-architecture images and publishes it under one tag, with no Docker daemon.
When each architecture is built and pushed separately, manifest-tool stitches them into a single multi-arch tag so docker pull image:tag resolves to the right arch automatically.
What it does
manifest-tool reads several per-arch images that are already in a registry and creates a manifest list (image index) that points at each one, pushing the list under a target tag. It runs daemonless, unlike the older docker manifest which needs experimental mode.
Common usage
# from arguments: template with ARCH/OS placeholders
manifest-tool push from-args \
--platforms linux/amd64,linux/arm64 \
--template ghcr.io/acme/app:1.4.0-ARCH \
--target ghcr.io/acme/app:1.4.0
# from a YAML spec file
manifest-tool push from-spec manifest.yamlOptions
| Flag | What it does |
|---|---|
| push from-args | Build the list from command-line template + platforms |
| push from-spec <file> | Build the list from a YAML spec |
| --platforms <list> | os/arch pairs to include (from-args) |
| --template <ref> | Per-arch image name with ARCH/OS/VARIANT placeholders |
| --target <ref> | The multi-arch tag to publish |
| --username / --password | Registry credentials |
In CI
A common matrix build pushes app:tag-amd64 and app:tag-arm64 from separate runners, then a final job runs manifest-tool to publish app:tag as the multi-arch list. The ARCH placeholder in --template maps to each platform automatically.
Common errors in CI
"manifest unknown" for a platform means the per-arch image was never pushed under the templated name; check the tag suffix. "unauthorized: authentication required" means pass --username/--password or use a docker config. If docker pull still gets the wrong arch, the list was not actually pushed to --target, or the platforms in the list are mislabeled.