Filters
How to search
  • Plain words find names, texts and examples.
  • "two words" finds the exact phrase.
  • --name or -x finds an option.
  • #word looks only inside commands.
  • @grep finds lessons and labs that use grep.
  • Filters: cat:network · in:labs · in:notes · level:rhcsa · ch:8 · root:yes. Put ! before a word to leave it out. OR between words means one of them.
  • ↑ ↓ to move · Enter to open · Esc to close · / to search

skopeo

Inspect, copy, sync and delete container images in registries — without pulling them and without a container engine.

Level
Extra
Group
Processes and jobs
Needs root
No
Package
skopeo

What it does

skopeo works directly with registries. skopeo inspect shows the labels, layers, architecture and digest of a remote image before you download it. skopeo copy moves an image between registries, local folders, archives and Podman storage — handy for mirrors in networks without internet. skopeo sync copies many images or tags at once. It also verifies and makes image signatures.

Images are named with a transport in front: docker:// (a registry), containers-storage: (Podman's local storage), dir: (a folder), oci: (an OCI layout folder), docker-archive: / oci-archive: (a tar file).

How to write it

skopeo [GLOBAL OPTION]... COMMAND [OPTION]... ARG...
skopeo inspect [OPTION]... TRANSPORT:IMAGE
skopeo copy [OPTION]... SOURCE DESTINATION

Main parts

Commands

inspect IMAGE
Show details of an image (labels, digest, layers, OS, arch).
copy SRC DST
Copy an image from one place to another.
sync --src T --dest T SRC DST
Copy many images or a whole repository.
list-tags IMAGE
List all tags of a repository.
delete IMAGE
Mark an image for deletion in a registry.
login / logout REGISTRY
Log in to / out of a registry.
manifest-digest FILE
Compute the digest of a manifest file.
generate-sigstore-key --output-prefix P
Make a sigstore key pair.
standalone-sign / standalone-verify
Sign or verify a manifest without a registry (debugging).

Transports

docker://REGISTRY/NAME:TAG
An image in a registry.
containers-storage:NAME
An image in the local Podman storage.
dir:PATH
Image files in a folder.
oci:PATH[:TAG]
An OCI image layout folder.
docker-archive:FILE / oci-archive:FILE
An image in a tar archive.

Options 32

Most used

Global options

--command-timeout=DURATION
Stop the command after this time.
--debug
Print debug output.
-h, --help
Show help.
--insecure-policy
Ignore the signature policy file.
--override-arch=ARCH
Use this architecture instead of the host's (arm64).
--override-os=OS
Use this OS instead of the host's.
--override-variant=VARIANT
Use this architecture variant.
--policy=FILE
Use this signature policy file.
--registries.d=DIR
Folder with registry configuration for signatures.
--tmpdir=DIR
Folder for temporary files.
-v, --version
Show the version.

inspect

--raw
Print the raw manifest.
--config
Print the image configuration (with --raw: raw config).
--format=TEMPLATE, -f
Go template output ({{.Digest}}).
--no-tags, -n
Do not list the tags of the repository.
--authfile=FILE / --creds=USER:PASS / --username / --password / --cert-dir=DIR / --tls-verify=BOOL / --retry-times=N
Login and TLS choices (also for copy, sync, list-tags, delete).

copy

--all, -a
Copy all architectures of a multi-arch image.
--multi-arch=MODE
system, all or index-only.
--src-creds=USER:PASS / --dest-creds=USER:PASS
Logins for the two sides.
--src-tls-verify=BOOL / --dest-tls-verify=BOOL
Check TLS on each side.
--format=FORMAT, -f
Write oci, v2s1 or v2s2 manifests.
--remove-signatures
Do not copy signatures.
--sign-by=KEY / --sign-by-sigstore-private-key=FILE
Sign the copy.
--preserve-digests
Fail if the digest would change.
--dest-compress-format=FMT
Compress layers with gzip or zstd.
--retry-times=N
Retry on network errors.
--quiet, -q
Less output.

sync

--src=TRANSPORT / --dest=TRANSPORT
docker, dir or yaml (a list file) as source; docker or dir as target.
--scoped
Keep the registry name in the target path.
--all, -a
All architectures.
--dry-run
Show what would be copied.
--keep-going
Do not stop at the first error.

Examples 11

$ run as a normal user# run as root (or with sudo)

  1. 1Look at a remote image without pulling it

    skopeo inspect docker://registry.access.redhat.com/ubi10/ubi
    skopeo inspect docker://registry.access.redhat.com/ubi10/ubi --format '{{.Name}} {{.Digest}} {{.Architecture}}'
    registry.access.redhat.com/ubi10/ubi sha256:4f0c... amd64

    Check the digest and labels before you trust an image.

  2. 2List the tags of a repository

    skopeo list-tags docker://registry.access.redhat.com/ubi10/ubi | head

    Choose a fixed tag (or a digest) instead of latest in production.

  3. 3See the ports and the start command of an image

    skopeo inspect --config docker://registry.access.redhat.com/ubi10/httpd-24 | jq '.config.ExposedPorts, .config.Cmd'
  4. 4Check an image for another architecture

    skopeo inspect --override-arch arm64 docker://registry.access.redhat.com/ubi10/ubi --format '{{.Architecture}}'
    arm64
  5. 5Copy an image into a private registry

    skopeo login registry.example.com
    skopeo copy docker://registry.access.redhat.com/ubi10/ubi:latest docker://registry.example.com/base/ubi10:latest

    No pull and push through local storage: the layers go straight from registry to registry.

  6. 6Copy all architectures of a multi-arch image

    skopeo copy --all docker://registry.access.redhat.com/ubi10/ubi docker://registry.example.com/base/ubi10
  7. 7Take images to a server without internet

    skopeo copy docker://registry.access.redhat.com/ubi10/httpd-24 oci-archive:httpd-24.tar
    scp httpd-24.tar admin@airgap1:/tmp/
    skopeo copy oci-archive:/tmp/httpd-24.tar containers-storage:localhost/httpd-24:latest

    On the offline server the image is now in Podman's storage.

  8. 8Copy a local Podman image to a registry

    skopeo copy containers-storage:localhost/myweb:1.0 docker://quay.io/s0sta/myweb:1.0
  9. 9Mirror a list of images with sync

    cat images.yaml
    registry.access.redhat.com:
      images:
        ubi10/ubi: [latest]
        ubi10/httpd-24: [latest]
    skopeo sync --src yaml --dest docker images.yaml registry.example.com/mirror
    skopeo sync --src docker --dest dir registry.access.redhat.com/ubi10/ubi /srv/mirror
  10. 10Pin an image by digest (DevSecOps)

    DIGEST=$(skopeo inspect docker://registry.access.redhat.com/ubi10/ubi --format '{{.Digest}}')
    echo "FROM registry.access.redhat.com/ubi10/ubi@$DIGEST"

    A digest never changes; a tag can. Pinned images make builds repeatable.

  11. 11Delete an old tag from a registry

    skopeo delete docker://registry.example.com/base/ubi10:old

Watch out

  • skopeo delete only marks the image; the registry removes the data at its next garbage collection.
  • --tls-verify=false turns off certificate checks. Use it only for a local test registry.
  • Login data is shared with Podman ($XDG_RUNTIME_DIR/containers/auth.json).

Files

/etc/containers/policy.json
Signature policy: which images must be signed by whom.
/etc/containers/registries.d/
Where signatures are stored per registry.
/etc/containers/registries.conf
Registries, mirrors and blocked registries.

Tips to remember

  • skopeo inspect … | jq gives you any field of the JSON.
  • Use skopeo sync in a cron job or timer to keep an internal mirror fresh.

Exit codes

0Success.
1An error (image not found, login failed, network error).