Cloud Native 8 min read

How to Build and Push Multi‑Architecture Docker Images with Buildx, Manifest, and Skopeo

This guide explains why building "once, run everywhere" containers is challenging across ARM and x86 platforms and provides step‑by‑step instructions for using Docker Buildx, Docker manifest, and Skopeo to create, tag, and push multi‑architecture images to a private registry.

Linux Ops Smart Journey
Linux Ops Smart Journey
Linux Ops Smart Journey
How to Build and Push Multi‑Architecture Docker Images with Buildx, Manifest, and Skopeo

In the era of containerized deployment, building “once, run everywhere” is challenging due to architecture mismatches such as Apple Silicon (ARM64) for local development versus x86_64 servers, edge devices using ARM while CI/CD runs on x86, and the need to rebuild and retag for each platform.

docker Buildx method

1. Dockerfile example:

$ cat Dockerfile
FROM docker.io/library/ubuntu:24.04

RUN sed -ri '[email protected]@mirrors.tuna.tsinghua.edu.cn@g' /etc/apt/sources.list.d/ubuntu.sources \
    && apt update && apt upgrade -y && apt clean autoclean \
    && rm -rf /tmp/* ~/.cache/* /var/lib/apt /var/cache/apt /var/log/apt /var/log/dpkg.log

2. Build and push a multi‑architecture image:

sudo docker buildx --builder mybuilder build --platform linux/amd64,linux/arm64 -t core.jiaxzeng.com/jiaxzeng/ubuntu:24.04 . --push
... (output omitted for brevity) ...

docker manifest method

1. Pull and push individual architecture images to Harbor:

# amd64
sudo docker pull --platform linux/amd64 docker.io/library/alpine:3.20
sudo docker tag docker.io/library/alpine:3.20 core.jiaxzeng.com/jiaxzeng/alpine:3.20-amd64
sudo docker push core.jiaxzeng.com/jiaxzeng/alpine:3.20-amd64

# arm64
sudo docker pull --platform linux/arm64 docker.io/library/alpine:3.20
sudo docker tag docker.io/library/alpine:3.20 core.jiaxzeng.com/jiaxzeng/alpine:3.20-arm64
sudo docker push core.jiaxzeng.com/jiaxzeng/alpine:3.20-arm64

2. Create and push a manifest list:

sudo docker manifest create core.jiaxzeng.com/jiaxzeng/alpine:3.20 \
    core.jiaxzeng.com/jiaxzeng/alpine:3.20-amd64 \
    core.jiaxzeng.com/jiaxzeng/alpine:3.20-arm64
sudo docker manifest push core.jiaxzeng.com/jiaxzeng/alpine:3.20

skopeo method

1. Install skopeo:

apt install skopeo

2. Log in to Harbor:

./skopeo --registries-conf registries.conf login core.jiaxzeng.com
Username: jiaxzeng
Password: …
Login Succeeded!

3. Configure registries.conf to use mirrors and allow insecure Harbor:

# cat registries.conf
[[registry]]
prefix = "docker.io"
location = "registry-1.docker.io"
mirror = [
    { location = "docker.1ms.run" },
    { location = "docker.mybacc.com" }
]

[[registry]]
prefix = "core.jiaxzeng.com"
location = "core.jiaxzeng.com"
insecure = true

4. Copy all architectures of an image (e.g., nginx) from Docker Hub to Harbor:

./skopeo --insecure-policy --registries-conf ./registries.conf copy --multi-arch all \
    docker://nginx:1.27-alpine3.20 docker://core.jiaxzeng.com/jiaxzeng/nginx:1.27-alpine3.20
... (output omitted for brevity) ...

Conclusion

Building and pushing multi‑architecture images addresses hardware heterogeneity and is a core skill for cloud‑native engineers.

Dockercontainerizationmanifestmulti-architectureBuildxskopeo
Linux Ops Smart Journey
Written by

Linux Ops Smart Journey

The operations journey never stops—pursuing excellence endlessly.

0 followers
Reader feedback

How this landed with the community

login 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.