How to Install and Use Skopeo for Container Image Management on RHEL 7

Skopeo is a command-line utility for performing operations on container images and image registries without requiring a running Docker daemon. It is part of the Open Container Initiative (OCI) ecosystem championed by Red Hat and is included in the standard RHEL extras and EPEL repositories. With Skopeo you can inspect image metadata, copy images between registries, list available tags, and mirror entire repositories — all without the overhead of pulling images to local Docker storage. On RHEL 7 systems where running a full Docker daemon is undesirable, or in CI pipelines where image promotion between registries is required, Skopeo is an indispensable tool.

Prerequisites

  • RHEL 7 with active subscription, or CentOS 7 with EPEL enabled
  • Root or sudo access for package installation
  • Network access to source and destination container registries
  • Credentials for any private registries you intend to use
  • Optional: Docker CE installed if you want to compare behaviour with the Docker CLI

Step 1: Installing Skopeo on RHEL 7

On a registered RHEL 7 system, Skopeo is available in the extras channel. Enable the channel and install:

sudo subscription-manager repos --enable=rhel-7-server-extras-rpms
sudo yum install -y skopeo
skopeo --version

On CentOS 7 or RHEL 7 without a subscription, install from EPEL:

sudo yum install -y epel-release
sudo yum install -y skopeo
skopeo --version

Verify the installation and check the default policy file location:

which skopeo
rpm -qi skopeo
ls /etc/containers/

Step 2: Understanding Skopeo Image Transport Prefixes

Skopeo uses transport prefixes to specify where images come from or go to. Understanding these prefixes is essential for constructing copy and inspect commands:

  • docker:// — A remote Docker registry (Docker Hub, quay.io, private registries)
  • docker-daemon: — The local Docker daemon image store
  • oci: — An OCI image layout directory on disk
  • oci-archive: — A tar archive containing an OCI image layout
  • docker-archive: — A tar archive in Docker format (compatible with docker load)
  • dir: — A directory containing a raw image manifest and layer blobs
  • containers-storage: — The local Podman/Buildah container storage

Step 3: Inspecting Images Without Pulling

One of Skopeo’s most useful features is the ability to inspect an image’s metadata — configuration, layers, labels, environment variables — without downloading the full image:

# Inspect a public image from Docker Hub
skopeo inspect docker://docker.io/nginx:latest

# Inspect with formatted JSON output piped to jq
skopeo inspect docker://docker.io/nginx:latest | python -m json.tool

# Inspect a specific architecture variant
skopeo inspect --override-arch amd64 docker://docker.io/nginx:latest

# Inspect a private registry image (with credentials)
skopeo inspect 
  --creds myuser:mypassword 
  docker://registry.example.com/myapp:production

The output shows the image’s configuration digest, environment variables, exposed ports, labels, and layer digests — without transferring a single layer blob to disk.

Step 4: Listing Available Tags

Before copying or pulling an image, you often want to see what tags are available in a repository. Skopeo’s list-tags subcommand queries the registry API directly:

# List all tags for a public image
skopeo list-tags docker://docker.io/library/postgres

# List tags on a private registry
skopeo list-tags 
  --creds myuser:mypassword 
  docker://registry.example.com/myorg/myapp

# List tags on a registry with a self-signed certificate
skopeo list-tags 
  --tls-verify=false 
  docker://registry.internal.example.com/myapp

The output is a JSON object with a Tags array, which you can filter with standard UNIX tools:

skopeo list-tags docker://docker.io/library/node | 
  python -c "import sys,json; tags=json.load(sys.stdin)['Tags']; 
  [print(t) for t in tags if t.startswith('18')]"

Step 5: Copying Images Between Registries

The skopeo copy command is the core of Skopeo’s image management capability. It copies images directly between any two locations without buffering through the Docker daemon:

# Copy from Docker Hub to a private registry
skopeo copy 
  docker://docker.io/nginx:1.25 
  docker://registry.example.com/mirror/nginx:1.25

# Copy with authentication for both source and destination
skopeo copy 
  --src-creds srcuser:srcpassword 
  --dest-creds destuser:destpassword 
  docker://source-registry.example.com/app:v2.1 
  docker://dest-registry.example.com/app:v2.1

# Copy to a local OCI directory (useful for air-gapped transfers)
skopeo copy 
  docker://docker.io/nginx:latest 
  oci:/tmp/nginx-oci:latest

# Copy from OCI directory back to a registry
skopeo copy 
  oci:/tmp/nginx-oci:latest 
  docker://registry.example.com/mirror/nginx:latest

To copy all platform variants (multi-arch manifest) in a single operation, use the --all flag:

skopeo copy --all 
  docker://docker.io/library/alpine:3.18 
  docker://registry.example.com/mirror/alpine:3.18

Step 6: Saving and Loading Images Without a Daemon

For transferring images to air-gapped environments, copy to a Docker-compatible tar archive that can be loaded directly with docker load:

# Save image as docker-archive tar (compatible with docker load)
skopeo copy 
  docker://docker.io/postgres:15 
  docker-archive:/tmp/postgres15.tar:postgres:15

# Transfer to air-gapped host and load
scp /tmp/postgres15.tar airgapped-host:/tmp/
# On the air-gapped host:
docker load -i /tmp/postgres15.tar
docker images | grep postgres

Step 7: Mirroring Repositories with skopeo sync

The skopeo sync command mirrors entire repositories or specific tag sets in a single operation. This is ideal for maintaining a local mirror of upstream images for disconnected environments:

# Create a sync configuration file
cat > /etc/skopeo/sync-config.yaml <<'EOF'
docker.io:
  images:
    nginx:
      - "1.24"
      - "1.25"
      - "latest"
    postgres:
      - "15"
      - "15-alpine"
  images-by-tag-regex:
    node:
      - "^18-alpine"
EOF

# Sync to a private registry
skopeo sync 
  --src yaml 
  --dest docker 
  --dest-creds admin:password 
  /etc/skopeo/sync-config.yaml 
  registry.example.com/mirror

# Sync to a local OCI directory for offline transfer
skopeo sync 
  --src yaml 
  --dest dir 
  /etc/skopeo/sync-config.yaml 
  /mnt/usb/image-mirror/

Set up a cron job on RHEL 7 to run the sync on a schedule, ensuring the mirror stays current:

cat > /etc/cron.d/skopeo-mirror <<'EOF'
0 2 * * * root /usr/bin/skopeo sync 
  --src yaml --dest docker 
  --dest-creds admin:password 
  /etc/skopeo/sync-config.yaml 
  registry.example.com/mirror 
  >> /var/log/skopeo-sync.log 2>&1
EOF

Step 8: Configuring policy.json for Image Verification

Skopeo uses /etc/containers/policy.json to enforce signature verification policies. The default on RHEL 7 requires images from registry.access.redhat.com to be signed, while allowing all others. You can customise this to enforce signing for your private registry:

cat /etc/containers/policy.json

# Example: require signatures for your private registry
cat > /etc/containers/policy.json <<'EOF'
{
  "default": [{"type": "insecureAcceptAnything"}],
  "transports": {
    "docker": {
      "registry.example.com": [
        {
          "type": "signedBy",
          "keyType": "GPGKeys",
          "keyPath": "/etc/containers/registry.example.com.pub"
        }
      ],
      "registry.access.redhat.com": [
        {
          "type": "signedBy",
          "keyType": "GPGKeys",
          "keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release"
        }
      ]
    }
  }
}
EOF

To skip policy verification temporarily during testing, use the --policy flag with a permissive policy file or pass --insecure-policy:

skopeo copy --insecure-policy 
  docker://docker.io/nginx:latest 
  docker://registry.example.com/test/nginx:latest

Conclusion

Skopeo fills a critical gap in the container toolchain on RHEL 7 by enabling registry operations without a running Docker daemon. Whether you are promoting images through CI/CD pipelines, mirroring upstream images for disconnected environments, auditing image metadata before deployment, or enforcing signature policies across your registry infrastructure, Skopeo provides a lightweight and scriptable solution. Its support for multiple transport formats makes it a versatile bridge between different image storage systems, and its integration with the OCI ecosystem ensures long-term compatibility with the broader container tooling landscape on Red Hat Enterprise Linux.