Copy Container Images Like a Pro

Kaushal KishoreKaushal Kishore
5 min read

Copy Container Images Like a Pro

Introduction

In the world of containerization and DevOps, copying container images from one repository to another is a fundamental skill that every developer and operations engineer must master. Whether you're migrating images due to Docker Hub's rate limiting, mirroring public images in your company's internal registry, or simply relocating images to a different repository, understanding the right tools and techniques can save you significant time and effort.

This comprehensive guide will walk you through the journey from basic single-platform image copying to advanced multi-platform repository cloning, sharing real-world insights and debugging experiences along the way.

Understanding Container Image Structure

Before diving into the copying techniques, it's crucial to understand the anatomy of a container image name:

Plain Text

registry.domain.com/repository/path:tag@digest
  • Registry Domain: Where the image is hosted (e.g., docker.io, gcr.io)

  • Repository Path: The namespace and image name

  • Tag: Version identifier (e.g., latest, v1.0)

  • Digest: SHA256 hash for immutable reference

Challenge 1: Basic Single-Platform Image Copy

The Traditional Approach

The most straightforward method uses the classic Docker CLI trio:

Bash

# Pull the image
docker pull source-registry.com/myapp:v1.0

# Tag for destination
docker tag source-registry.com/myapp:v1.0 target-registry.com/myapp:v1.0

# Push to destination
docker push target-registry.com/myapp:v1.0

What I Learned

  • This method is simple and works well for small images

  • Requires Docker daemon running with sufficient privileges

  • Images are downloaded completely to local storage before re-uploading

Debugging Experience

Initially, I encountered authentication issues when pushing to private registries. The solution was properly configuring Docker credentials:

Bash

docker login target-registry.com
# Or use credential helpers for better security

Difficulty Level: ⭐⭐ (Easy)

Challenge 2: The Pro Way - Efficient Image Copying

Advanced Tools Overview

For production environments, specialized tools offer better performance and security:

1. Skopeo

Bash

skopeo copy docker://source-registry.com/myapp:v1.0 docker://target-registry.com/myapp:v1.0

2. Crane (from Google's go-containerregistry)

Bash

crane copy source-registry.com/myapp:v1.0 target-registry.com/myapp:v1.0

3. Regctl (from regclient)

Bash

regctl image copy source-registry.com/myapp:v1.0 target-registry.com/myapp:v1.0

What I Learned

  • Skopeo: Most feature-rich, supports various storage backends

  • Crane: Lightweight, fast, and simple to use

  • Regctl: Excellent for automation and scripting

Debugging Experience

When working with self-signed certificates, I had to configure TLS verification:

Bash

# Skopeo
skopeo copy --src-tls-verify=false --dest-tls-verify=false ...

# Crane
crane copy --insecure ...

Difficulty Level: ⭐⭐⭐ (Medium)

Challenge 3: Multi-Platform Image Copying

The Complexity of Multi-Platform Images

Multi-platform images are actually manifest lists containing multiple image variants for different architectures (amd64, arm64, etc.). Copying them requires special handling.

Using Docker Buildx

Bash

# Inspect the multi-platform image
docker buildx imagetools inspect source-registry.com/myapp:v1.0

# Copy preserving all platforms
docker buildx imagetools create \
  --tag target-registry.com/myapp:v1.0 \
  source-registry.com/myapp:v1.0

Using Crane

Bash

# Crane handles multi-platform images automatically
crane copy source-registry.com/myapp:v1.0 target-registry.com/myapp:v1.0

What I Learned

  • Multi-platform images require manifest list handling

  • Not all tools preserve platform information correctly

  • Always verify platform support after copying

Debugging Experience

Initially, I lost platform variants when using basic Docker commands. The solution was using tools that understand manifest lists:

Bash

# Verify all platforms are preserved
crane manifest source-registry.com/myapp:v1.0 | jq '.manifests[].platform'

Difficulty Level: ⭐⭐⭐⭐ (Medium-Hard)

Challenge 4: Repository Cloning - The Ultimate Challenge

Copying All Tags and Variants

The most complex scenario involves cloning entire repositories with all tags and platform variants.

Using Skopeo for Bulk Operations

Bash

# List all tags
skopeo list-tags docker://source-registry.com/myapp

# Copy all tags (requires scripting)
for tag in $(skopeo list-tags docker://source-registry.com/myapp | jq -r '.Tags[]'); do
  skopeo copy docker://source-registry.com/myapp:$tag docker://target-registry.com/myapp:$tag
done

Using Crane for Repository Sync

Bash

# Copy all tags at once
crane copy source-registry.com/myapp target-registry.com/myapp --all-tags

What I Learned

  • Repository cloning requires careful planning for large repositories

  • Rate limiting becomes a significant concern

  • Parallel copying can improve performance but may overwhelm registries

Debugging Experience

Large repository cloning initially failed due to rate limiting and network timeouts. I implemented retry logic and parallel processing:

Bash

# Add retry mechanism
for i in {1..3}; do
  if crane copy source-registry.com/myapp:$tag target-registry.com/myapp:$tag; then
    break
  fi
  sleep $((i * 2))
done

Difficulty Level: ⭐⭐⭐⭐⭐ (Hard)

Tool Comparison and Recommendations

Ease of Use Ranking

  1. Crane - Simple, intuitive, handles most scenarios automatically

  2. Docker CLI - Familiar but limited for complex scenarios

  3. Regctl - Powerful but requires more configuration

  4. Skopeo - Most feature-rich but steeper learning curve

Performance Comparison

  • Crane: Fastest for simple operations

  • Skopeo: Best for complex filtering and transformations

  • Regctl: Excellent for automation and CI/CD pipelines

  • Docker CLI: Slowest due to local storage requirement

Best Practices and Tips

1. Authentication Management

Bash

# Use credential helpers instead of docker login
export DOCKER_CONFIG=/path/to/secure/config

2. Bandwidth Optimization

Bash

# Use compression for large images
skopeo copy --compression-format gzip ...

3. Verification

Bash

# Always verify copied images
crane digest source-registry.com/myapp:v1.0
crane digest target-registry.com/myapp:v1.0

4. Error Handling

Bash

# Implement proper error handling in scripts
set -euo pipefail

Common Pitfalls and Solutions

1. Platform Architecture Loss

Problem: Copying multi-platform images results in single-platform copies Solution: Use tools that preserve manifest lists (crane, skopeo with proper flags)

2. Rate Limiting

Problem: Hitting registry rate limits during bulk operations Solution: Implement exponential backoff and parallel processing limits

3. Authentication Expiry

Problem: Long-running operations fail due to token expiry Solution: Refresh tokens periodically or use service account credentials

Conclusion

Mastering container image copying is essential for modern DevOps workflows. Starting with basic Docker commands and progressing to specialized tools like crane, skopeo, and regctl provides the flexibility needed for various scenarios.

My journey through these challenges taught me that while Docker CLI is great for learning, production environments benefit significantly from specialized tools. Crane emerged as my go-to tool for its simplicity and reliability, while skopeo proved invaluable for complex transformations.

Remember: always test your image copying strategy in a development environment before applying it to production, and consider implementing monitoring and alerting for critical image synchronization tasks.

Tags

#DevOps #Docker #Containers #crane #skopeo #regctl #ContainerRegistry #kubernetes #CI/CD #ImageManagement #containerization #registry #docker-hub #infrastructure #automatio

10
Subscribe to my newsletter

Read articles from Kaushal Kishore directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kaushal Kishore
Kaushal Kishore

Currently working as a Network Operations Center (NOC) Engineer at Verizon Networks under HCLTech as a Graduate Engineer Trainee (GET), I specialize in monitoring and maintaining critical network infrastructures. While I ensure seamless network uptime and resolve incidents at the provider level, I am also deeply passionate about transitioning into the DevOps space. With hands-on exposure to CI/CD pipelines, Docker, GitHub Actions, Ansible, and other modern DevOps tools, I am consistently upskilling to bridge the gap between operations and development. My journey reflects a dynamic shift from traditional NOC responsibilities to automation-driven DevOps workflows—combining reliability, efficiency, and innovation.