Self-hosted service
podman-container-tools/skopeo avatar
podman-container-tools/skopeo

Skopeo: working with remote container images without a daemon

Work with remote images registries - retrieving information, images, signing content

11,275 stars955 forksGoApache-2.0

At a glance

What is it?
Skopeo is a Go command line utility for inspecting, copying, syncing and deleting container images across registries and local stores. It needs no daemon and, for most operations, no root, which makes it a practical fit for CI and air-gapped mirroring.
Who is it for?
Adopt Skopeo if you need to move or inspect images from a CI runner, a build host or an air-gapped mirror without running a daemon or holding root. Do not adopt it as a replacement for a container runtime: it does not run containers, and it is the wrong tool for building images.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap Skopeo fills between a registry and a running container

Most container tooling assumes you want to run something. Docker and Podman pull an image into local storage so a container can start from it, and the pull is the side effect you pay for. Skopeo inverts that. The README describes it as a command line utility that performs operations on container images and image repositories, and the operations it lists are copying, inspecting, deleting and syncing. Pulling to run is not among them.

The audience follows from that. If you need to know what an image contains before it touches a disk, Skopeo is built for the question. The inspect command fetches the repository manifest and prints a docker inspect-like JSON document, so you can read tags, labels, creation date, architecture, OS, environment variables and layer sizes without downloading layers. A CI job that wants to confirm a base image digest, or a security review that wants the layer list, can do that against the registry directly.

The second audience is anyone moving images between stores. Copying from one registry to another, from a registry into a local directory, or into the containers-storage backend used by Podman, CRI-O and Buildah is a single command. The README notes this works without privilege. That matters on a build host where you would rather not grant a daemon socket.

How Skopeo addresses images: transports, not a local engine

Skopeo's central abstraction is the transport, the prefix before the colon in an image reference. The README enumerates them: containers-storage for a local containers/storage image store configured in /etc/containers/storage.conf, dir for a plain directory of manifest, layer tarballs and signatures, docker:// for a registry speaking the Docker Registry HTTP API V2, docker-archive for a docker save-formatted file, docker-daemon for the Docker daemon's internal storage, and oci for a directory laid out per the Open Container Image Layout Specification.

Because both sides of a copy are transports, the tool composes: docker:// to docker://, docker:// to dir, docker-archive to containers-storage. There is no intermediate local image store unless you name one. The README states Skopeo works with OCI images and the original Docker v2 images, so the format conversion is handled inside the copy rather than by you.

Authentication is likewise transport-level. For docker:// the README says the default is the authorization state in $XDG_RUNTIME_DIR/containers/auth.json, which skopeo login writes. Credentials and certificates are passed when the repository requires them. The design keeps registry interaction stateless per invocation, which is why no daemon is needed: each command opens the transports it was given and exits.

Installing Skopeo and inspecting an image for the first time

The README points to install.md for detailed installation and build instructions, and states there is no separate project website: this repository and the container images it documents are the only upstream builds. Distribution packages are explicitly allowed as an option, with the caveat that other sites presenting themselves as the home of Skopeo are not affiliated with the project.

The container image is the shortest path if you already have a runtime. The README gives quay.io/skopeo/stable as the location and links to the Skopeo Image page for details. Running that image is how you reach the command list without installing anything on the host. From there, the most common first real use is inspecting a public image without pulling it. The README's own example targets Fedora:

console
$ skopeo inspect docker://registry.fedoraproject.org/fedora:latest

The output is a JSON object with Name, Digest, RepoTags, Created, Labels, Architecture, Os, Layers and LayersData. LayersData carries each layer's MIMEType, Digest and Size, which is where the disk-space answer lives. If you only want the digest, the README shows piping to jq:

console
$ skopeo inspect docker://registry.fedoraproject.org/fedora:latest | jq '.Digest'

For the container configuration rather than the manifest summary, add --config. The README's example pipes that to jq and shows created, architecture, os, config with Env, Cmd and Labels, rootfs with diff_ids, and history. That is the flag to reach for when you want the environment variables or the entrypoint before deciding whether to pull. The README also documents the reverse direction, a registry-to-registry copy starting from quay.io/buildah/stable, which is the same transport syntax with a different prefix on each side.

Copying and syncing, and where the model gets awkward

Copying is the operation the README leads with: images move between registries, containers/storage, the Docker daemon store, local directories and local OCI-layout directories. The example given is a registry-to-registry copy starting from quay.io/buildah/stable. Syncing is the bulk version, described as syncing an external image repository to an internal registry for air-gapped deployments. That is the use case where Skopeo is hard to replace: a machine with no route to the internet can mirror a curated set of tags into an internal registry on a schedule.

The limitations are worth stating plainly. Skopeo does not run containers and does not build images; the README lists no build operation, and the transports describe image movement and inspection only. If your task is to produce an image, this is the wrong tool.

The dir transport is a real constraint rather than a feature. The README calls it a non-standardized format, primarily useful for debugging or noninvasive container inspection. Treating a dir: tree as a portable artifact format is a mistake the documentation itself warns against. Similarly, docker-daemon requires a running Docker daemon and a reference containing a tag or a digest, so it is the one transport that reintroduces the dependency Skopeo otherwise avoids.

Signature verification is where the documentation is thinnest. The repository ships a default-policy.json and the Makefile installs into a registries.d directory under CONTAINERSCONFDIR, defaulting to /etc/containers, but the README excerpt does not document the policy format or how a verification failure surfaces. Verify that against docs/ before you depend on it in a gated pipeline.

Skopeo versus crane and the registry HTTP API

The closest alternative in spirit is crane, part of go-containerregistry. Both are daemonless CLIs that talk to registries directly, and both can copy and inspect without a local engine. The difference is in what sits underneath. Skopeo delegates to go.podman.io/image/v5, the same library family that Podman, CRI-O and Buildah use for image handling, and it speaks the containers/image transport vocabulary, including containers-storage and the /etc/containers configuration. If your environment is already Podman-shaped, Skopeo shares its storage backend and its policy files, so a copy lands where Podman expects to find it.

crane is a single static Go binary oriented around the registry API itself, with a flatter command surface and no containers/storage integration. If you want to move images between registries and never touch a local store, that orientation is simpler. If you want the image to end up in the store your runtime already reads, Skopeo's transport model does that without an export and import step.

The third option is not a tool at all: calling the registry API directly. That works until you need authentication handling, manifest format differences between Docker v2 and OCI, or signature and policy checks. Those are the parts Skopeo is assembled from, and reimplementing them is rarely the point of the task.

Maintenance, packaging and licence

The repository is not archived, and the last push was on 2026-09-20, one day before this writing. Recent releases in the repository are v1.24.1 and v1.22.3, both dated 2026-09-16, and v1.24.0 from 2026-07-30. The presence of a maintenance release on the older 1.22 line alongside a new 1.24 line suggests backported fixes rather than a single moving target, which is worth knowing if you pin a version.

Upgrade cost is mostly a packaging question. The project builds with Go, and go.mod declares go 1.26.0 with a warning that the go and toolchain versions should match exactly to prevent unwanted auto-updates. Building from source therefore means matching that toolchain. The Makefile exposes install, install-binary and install-completions targets with PREFIX defaulting to /usr/local, and it installs configuration into CONTAINERSCONFDIR, which is /etc/containers on Linux and /usr/local/etc/containers on FreeBSD. The Makefile also selects CONTAINER_RUNTIME as podman when available, falling back to docker.

Licensing is Apache-2.0 per the repository. That is permissive, and the practical implication for most users is that redistribution and modification are allowed with the usual notice and patent terms. This is not legal advice; check the LICENSE file and your own obligations, particularly if you vendor the code or ship the container image.

One governance detail worth noting for a project this widely packaged: the repository carries an LLM_POLICY.md alongside CONTRIBUTING.md and GOVERNANCE.md, so contribution norms around generated code are stated in-tree rather than left implicit.

Editorial conclusion

Adopt Skopeo if you need to move or inspect images from a CI runner, a build host or an air-gapped mirror without running a daemon or holding root. Do not adopt it as a replacement for a container runtime: it does not run containers, and it is the wrong tool for building images. Before relying on it, verify which version your distribution ships, whether your registry requires credentials in $XDG_RUNTIME_DIR/containers/auth.json, and how your policy file in /etc/containers/policy.json treats unsigned images.

Frequently asked questions

What is Skopeo used for?

Skopeo performs operations on container images and image repositories: copying images between registries and local stores, inspecting a remote image without pulling it, deleting an image from a repository, and syncing an external repository to an internal registry for air-gapped deployments. It does not require root for most operations and does not require a daemon.

What does the name Skopeo mean?

The README does not explain the origin of the name, so the repository does not support an answer. What it does state is that Skopeo has no separate project website and that this repository plus the documented container images are the only upstream builds.

How to install Skopeo?

The README points to install.md for detailed installation and build instructions. It also states that Skopeo is available as a container image at quay.io/skopeo/stable, and that packages from distributions you trust are an option, while other sites presenting themselves as the home of Skopeo are not affiliated with the project.

How do you use skopeo inspect?

The inspect command fetches a repository's manifest and prints a docker inspect-like JSON document about a repository or a tag. The README's example runs skopeo inspect docker://registry.fedoraproject.org/fedora:latest, and adding --config returns the container configuration instead of the manifest summary.

Does Skopeo run on Windows or macOS?

The repository does not describe Windows or macOS support directly. The Makefile does branch on uname -s for FreeBSD, using /usr/local/etc/containers as CONTAINERSCONFDIR, and it notes the use of command -v rather than which for compatibility with MacOS, which indicates the build is expected to work there.

What is skopeo copy?

Copy moves an image between two storage mechanisms named as transports, such as docker:// to docker:// or docker:// to containers-storage. The README's example copies from quay.io/buildah/stable to another registry, and the README notes this works without privilege.

Official sources

  1. License: Apache-2.0
  2. podman-container-tools/skopeo on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/podman-container-tools-skopeo.svg)](https://hysenlabs.com/projects/podman-container-tools-skopeo)