Skip to content
Latchkey

skopeo copy: Move Images Between Registries

skopeo copy streams an image from a source transport to a destination transport without pulling it into a local daemon.

Mirroring images between registries is a common CI job. skopeo copy does it directly, registry to registry, with no docker pull/push round trip and no daemon.

What it does

skopeo copy reads an image from a source transport (for example docker://) and writes it to a destination transport, copying manifests and blobs directly. Because it never unpacks into a daemon, it runs in a plain container or a rootless CI runner.

Common usage

Terminal
# registry to registry, no local pull
skopeo copy docker://docker.io/library/nginx:1.25 docker://ghcr.io/acme/nginx:1.25

# with per-side credentials
skopeo copy \
  --src-creds "$SRC_USER:$SRC_PASS" \
  --dest-creds "$DST_USER:$DST_PASS" \
  docker://registry.example.com/app:sha docker://ghcr.io/acme/app:sha

# copy every arch of a multi-arch index
skopeo copy --all docker://alpine:3.20 docker://ghcr.io/acme/alpine:3.20

Options

FlagWhat it does
--src-creds user:passCredentials for the source registry
--dest-creds user:passCredentials for the destination registry
--allCopy the whole manifest list (every architecture), not just one
--src-tls-verify=falseSkip TLS verification on the source (insecure registries)
--dest-tls-verify=falseSkip TLS verification on the destination
--format oci|v2s2Output manifest format (OCI or Docker schema 2)
--retry-times NRetry failed blob transfers N times

In CI

skopeo copy is the canonical way to promote an image between registries without pulling it locally: no docker pull then docker push, no daemon, and it works rootless. Prefer --src-creds/--dest-creds (or skopeo login) over a shared docker config when the two sides use different accounts.

Common errors in CI

"unauthorized: authentication required" means missing or wrong credentials for that side; set --src-creds/--dest-creds or run skopeo login. "manifest unknown" means the source tag or digest does not exist. "error copying image: ... x509: certificate signed by unknown authority" on an internal registry needs --src-tls-verify=false or a mounted CA. "Requested but not honored" on --all against a single-arch image is harmless.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →