Operations 10 min read

Migrate Docker Images Across Registries and Architectures Using Buildx

This guide explains three methods for moving Docker images between registries—including simple tag‑and‑push, Buildx multi‑platform builds, and manifest‑based migrations—detailing step‑by‑step commands, required variables, pros and cons, and troubleshooting tips for both single‑arch and cross‑architecture image transfers.

Go Programming World
Go Programming World
Go Programming World
Migrate Docker Images Across Registries and Architectures Using Buildx

Single‑Platform Image Migration

For non‑cross‑platform images, migration is straightforward:

Pull the source image: docker pull <IMAGE> Retag it for the target registry: docker tag <SOURCE_IMAGE> <TARGET_IMAGE> Push the retagged image: docker push <TARGET_IMAGE> Optional cleanup: docker rmi <IMAGE> to free local disk space.

Before pushing, run docker login to authenticate with the target registry and avoid using the latest tag in production.

Why Single‑Platform Migration Is Limited

This approach only pulls the image matching the host CPU architecture, so migrating from an x86 host to an ARM node would produce an image that cannot run on the target architecture.

Cross‑Platform Image Migration with Buildx

Example: migrate golang:1.25-alpine from Docker Hub to an Alibaba Cloud private registry.

Method 1: Buildx Multi‑Platform Build and Push

Initialize a builder if needed:

$ docker buildx create --name mybuilder --use
$ docker buildx inspect --bootstrap

One‑line command to build and push both amd64 and arm64 images:

TARGET="crpi-1ql0kmu5z0c9xt5q.cn-hangzhou.personal.cr.aliyuncs.com/jianghushinian/golang:1.25-alpine"
echo "FROM golang:1.25-alpine" | docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t ${TARGET} \
  --push -

Alternatively, create and push a manifest without a Dockerfile:

SOURCE="golang:1.25-alpine"
TARGET="crpi-1ql0kmu5z0c9xt5q.cn-hangzhou.personal.cr.aliyuncs.com/jianghushinian/golang:1.25-alpine"
docker buildx imagetools create --tag ${TARGET} ${SOURCE}

Comparison of Buildx Commands

docker buildx build : Rebuilds images; consumes bandwidth and storage; performance depends on network and image size; requires a running BuildKit instance.

docker buildx imagetools : Manipulates manifests only; transfers only a few kilobytes of JSON; completes in seconds; needs only registry API access; cannot modify image contents.

Cross‑Platform Migration Using Traditional Pull/Push and Manifest

If Buildx is unavailable, the classic pull/push combined with docker manifest works.

# Variables
VERSION="1.25-alpine"
SOURCE_IMAGE="golang:${VERSION}"
TARGET_REPO="crpi-1ql0kmu5z0c9xt5q.cn-hangzhou.personal.cr.aliyuncs.com/jianghushinian/golang"

# amd64
docker pull --platform=linux/amd64 ${SOURCE_IMAGE}
docker tag ${SOURCE_IMAGE} ${TARGET_REPO}:${VERSION}-amd64
docker push ${TARGET_REPO}:${VERSION}-amd64

# arm64
docker pull --platform=linux/arm64 ${SOURCE_IMAGE}
docker tag ${SOURCE_IMAGE} ${TARGET_REPO}:${VERSION}-arm64
docker push ${TARGET_REPO}:${VERSION}-arm64

# Create multi‑arch manifest
docker manifest create ${TARGET_REPO}:${VERSION} \
  ${TARGET_REPO}:${VERSION}-amd64 \
  ${TARGET_REPO}:${VERSION}-arm64

# Push manifest
docker manifest push ${TARGET_REPO}:${VERSION}

This method is manual but reliable and helps understand the underlying distribution mechanism.

Tool Selection and Troubleshooting

Buildx imagetools offers the fastest, bandwidth‑light migration, but some registries may reject it, producing errors such as “ERROR: failed commit on ref … unexpected size 0”. In those cases, fall back to docker buildx build or the traditional docker manifest workflow. Third‑party tools like Skopeo or Crane also provide one‑line migrations and integrate well with CI/CD pipelines.

Conclusion

For extreme efficiency, use docker buildx imagetools to sync manifests without pulling image layers.

For full control and compatibility, use docker buildx build with BuildKit to rebuild and push images.

For learning, fallback, or environments lacking Buildx, use the classic docker pull/push plus docker manifest approach.

registryimage migrationbuildxMulti-Arch
Go Programming World
Written by

Go Programming World

Mobile version of tech blog https://jianghushinian.cn/, covering Golang, Docker, Kubernetes and beyond.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.