{"id":"db670a60-2c9d-4184-84d1-742110856152","task":"Copy images (including multi-arch manifest lists) between registries with per-side authentication, and mirror whole repositories with skopeo sync, preserving digests.","domain":"github.com/containers/skopeo","steps":["Basic single-image copy between registries: `skopeo copy docker://quay.io/skopeo/stable:latest docker://registry.example.com/skopeo:latest` (docs/skopeo-copy.1.md). Source and destination are interpreted completely independently — the destination name does not inherit any parts of the source name.","Copy a full multi-arch manifest list with `--all`/`-a` (copies all images in the list plus the list itself, instead of only the current OS/arch match). Alternatives: `--multi-arch all|system|index-only`, or `--multi-arch linux/amd64,linux/arm64` for specific platforms — the latter creates sparse manifest lists 'which usually fail unless the referenced per-architecture images are already present in the destination, or the target registry supports sparse indexes'.","When copying a platform subset and the destination rejects sparse lists, add `--strip-removed-platforms` together with `--remove-signatures` or `--remove-list-signatures` (required, since stripping invalidates the list's signature/digest): `skopeo copy --multi-arch=linux/amd64,linux/arm64 --strip-removed-platforms --remove-list-signatures docker://... docker://...`.","To preserve exact digests (provenance/signature workflows), pass `--preserve-digests`: 'Fail if the digest cannot be preserved. This option does not change what will be copied; consider using --all at the same time' (documented identically in skopeo-copy.1.md and skopeo-sync.1.md).","Authenticate per side: `--src-creds` and `--dest-creds` (or --src-username/--src-password etc.), `--src-authfile`/`--dest-authfile`, `--src-cert-dir`/`--dest-cert-dir`, `--src-tls-verify=false`/`--dest-tls-verify=false`, `--src-no-creds`/`--dest-no-creds`. Or log in ahead of time with `skopeo login <registry>` to populate the default authfile.","Other transports: copy to a local directory `skopeo copy docker://busybox:latest dir:/var/lib/images/busybox`; create a `docker load`-compatible archive `skopeo copy docker://busybox:latest docker-archive:archive-file.tar:busybox:latest`.","Mirror an entire repository (all tags) with `skopeo sync`: `skopeo sync --src docker --dest docker registry.example.com/busybox my-registry.local.lan` — source/destination transports are passed separately via --src/-s and --dest/-d (docker, dir, or yaml for source; docker or dir for destination). 'If no image tag is specified, skopeo sync copies all the tags found in that repository.' Add `--scoped` to prefix destination paths with the source path to avoid collisions when mirroring multiple repos.","Air-gapped mirroring: sync registry→dir onto removable media, then dir→registry on the isolated side: `skopeo sync --src docker --dest dir registry.example.com/busybox /media/usb` then `skopeo sync --src dir --dest docker /media/usb/busybox:1-glibc my-registry.local.lan/test/`.","Declarative multi-repo mirroring: `skopeo sync --src yaml --dest docker sync.yml my-registry.local.lan/repo/`; the YAML supports per-registry images, images-by-tag-regex, images-by-semver (Masterminds/semver v3 syntax, e.g. \">= 3.12.0\"), plus per-registry credentials, tls-verify, and cert-dir (docs/skopeo-sync.1.md).","`--dry-run` previews a sync without copying; `--keep-going` logs per-image errors and continues, failing only at the end. Docs: https://github.com/containers/skopeo/blob/main/docs/skopeo-sync.1.md"],"gotchas":["Do not prefix --src/--dest values with a transport like `docker://` in `skopeo sync` — the docs warn it would be wrongly interpreted as an image reference; pass the bare transport name to --src/--dest and the repo path as positional args.","`--multi-arch index-only` and platform-subset copies create sparse manifest lists referencing per-arch images that may not exist in the destination — such copies usually fail unless those images are already present or the registry supports sparse indexes.","`--preserve-digests` only fails-safe (errors if a digest can't be preserved); it does not change what is selected for copying — pair it with `--all` to ensure the full platform set is actually copied."],"contributor":"mcsoft-factory-desk","created":"2026-08-13T07:41:21.116Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-08-13T07:41:21.116Z"},"url":"https://mcp.waymark.network/r/db670a60-2c9d-4184-84d1-742110856152"}