Demystifying Docker Multi-Platform Builds and Manifests: A Brick by Brick Guide
Danish Khan

Danish Khan @deekay99

About: 15years exp. in Platform Engineering, seen and have been the part of the Tech shift from Monolith to Micro-Services to Self-hosting to Hyper-Scalers !!!!

Location:
India
Joined:
May 12, 2024

Demystifying Docker Multi-Platform Builds and Manifests: A Brick by Brick Guide

Publish Date: Jul 9
0 0

🧱 "One image. Multiple platforms. Zero surprises."

This is what Docker's multi-platform build and manifest system enables — and it's more relevant than ever in today’s hybrid infrastructure world.

Whether you’re:

  • Working on an M1 Mac but deploying to an x86 GKE cluster,
  • Building in CI/CD on an ARM-based runner but targeting AMD64 servers,
  • Or managing both OpenShift on-prem and GKE on cloud...

You need to build and tag Docker images the right way — to ensure your containers run reliably, regardless of where they're pulled.

In this article, we’ll go brick by brick to explore:

  • ✅ What is a multi-platform image build?
  • ✅ Why does Docker pull different images on different machines?
  • ✅ What exactly is a manifest and why does it matter?
  • ✅ How to enforce platform consistency across builds?
  • ✅ What breaks if you don’t use platform-aware builds?

And we’ll wrap it all up with:

  • 🧠 Real-world DevOps gotchas
  • 🛠️ Best practices for Jenkins and CI/CD pipelines
  • 📦 Storage and runtime behavior of platform-specific layers

Let’s get started. 🔍


🧱 What is a Docker Multi-Platform Build?

A multi-platform build allows you to create Docker images that can run on multiple CPU architectures (like amd64, arm64) from a single machine — even if that machine only supports one architecture.

🧠 Why It Matters

Different environments use different processor types:

  • 🖥️ Intel/AMD laptops and servers → amd64
  • 🍏 Apple M1/M2 Macs → arm64
  • 📦 Raspberry Pi → armhf, arm64
  • ☁️ AWS Graviton or GCP Tau T2A → arm64

If you don’t build platform-aware images, your container might fail to run on systems it wasn’t built for.


🔍 How Docker Identifies Your Architecture Automatically

When you run:

docker pull busybox
Enter fullscreen mode Exit fullscreen mode

Docker automatically knows your architecture using system calls like:

uname -m     # Returns x86_64 or arm64
Enter fullscreen mode Exit fullscreen mode

It uses this info to pull the correct platform image by default — no need for you to explicitly specify the platform unless you're cross-building.


📦 Why SHA256 Digests Differ for Each Platform

Even if the tag is the same (busybox:latest), the actual SHA256 digest is different for amd64 vs arm64.

Why?

Each platform compiles binaries differently, so:

  • Different binaries = different layers
  • Different layers = different image digests

🤔 What Happens If I Pull Two Platform Variants?

Let’s say you do:

docker pull --platform=linux/arm64 busybox
docker tag busybox busybox:arm64

docker pull --platform=linux/amd64 busybox
docker tag busybox busybox:amd64
Enter fullscreen mode Exit fullscreen mode

Now you have two tagged variants.

But if you just do:

docker run busybox
Enter fullscreen mode Exit fullscreen mode

It will run the latest pulled busybox:latest, which may or may not match your expected platform.

✅ Best Practice:

Explicitly tag and run the desired platform image:

docker run busybox:arm64
docker run busybox:amd64
Enter fullscreen mode Exit fullscreen mode

⚙️ How to Enforce Platform in Docker Build

If you're using a CI/CD pipeline (like Jenkins) or building locally, always fix the platform to avoid surprises:

docker buildx create --use   # once per agent
docker buildx build \
  --platform=linux/amd64 \
  -t myimage:1.0.0 \
  --push .
Enter fullscreen mode Exit fullscreen mode

This ensures the image is always built for amd64, regardless of whether you're on M1, x86, or in the cloud.


📍 Real-World Use Case: Same Image for On-Prem & Cloud

Assume you’re running:

  • On-prem OpenShift (OCP) setup
  • Target deployment on GCP GKE

Even if both runtime platforms are amd64, your CI runner may be arm64 (e.g., running on M1 Mac or ARM-based VM). If you don’t specify --platform, your build may accidentally produce an arm64 image, which won’t work in production.

✅ Solution

In Jenkins or your build script:

docker buildx build \
  --platform=linux/amd64 \
  -t registry.io/myapp:1.0.0 \
  --push .
Enter fullscreen mode Exit fullscreen mode

You can also verify the platform post-build:

docker image inspect myapp:1.0.0 \
  --format='{{.Architecture}}/{{.Os}}'
Enter fullscreen mode Exit fullscreen mode

📈 Will Multi-Platform Build Increase Image Size?

Registry Size:

Yes, total size increases because each architecture has its own full image:

  • amd64: 100MB
  • arm64: 90MB → Registry now stores ~190MB

Local Size:

No, unless you --load all variants locally (default keeps only the last one).

Runtime Download:

✅ Efficient — Docker pulls only the matching platform image for the host.


📜 Deep Dive into Docker Manifests

🤖 What is a Manifest?

A Docker manifest is a metadata file that maps a Docker image tag to the correct image version for each platform.

Think of it as a:

📦 Smart label that says “if you’re on amd64, pull this; if arm64, pull that.”

It allows the same tag (myapp:latest) to point to multiple images, depending on who’s asking.


📖 Real-World Analogy

🍔 A restaurant has one menu item: "Burger".

If an Indian orders, they get a veg burger.

If an American orders, they get a beef burger.

If a Middle Easterner orders, they get a lamb burger.

They all just said “burger” — but they got what’s right for them.

Similarly:

docker pull myapp:latest
Enter fullscreen mode Exit fullscreen mode

returns a platform-specific image — thanks to the manifest.


🔬 What’s Inside a Manifest?

{
  "manifests": [
    {
      "platform": { "architecture": "amd64", "os": "linux" },
      "digest": "sha256:aaa..."
    },
    {
      "platform": { "architecture": "arm64", "os": "linux" },
      "digest": "sha256:bbb..."
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

🔍 How to Inspect a Manifest

docker buildx imagetools inspect myapp:latest
Enter fullscreen mode Exit fullscreen mode

✅ What Problems It Solved

Problem Solved By Manifest
One tag = one platform only One tag supports many platforms
Manual selection of image Automatic matching by Docker
Broken builds on ARM/M1 Seamless image pulls
Multiple tags to manage Single tag, multi-arch supported

✅ Final Best Practices Summary

Task Recommendation
CI builds on mixed-arch runners Always use --platform in docker buildx build
Multi-platform support Build with --platform=linux/amd64,linux/arm64 and push manifest
Save registry space Build only required platforms
Keep platform control Tag each variant explicitly (e.g., myapp:arm64)
Validate architecture Use docker inspect or CI assertions

🔚 Conclusion

Understanding Docker’s multi-platform builds and manifests is essential in today’s hybrid infrastructure world. Whether you're building locally, on Jenkins, deploying to GKE, or OpenShift — platform consistency matters.

One tag. Many platforms. No surprises.

That's the power of Docker Manifests.


Want to learn how to write your own manifest manually or automate this via Jenkins or GitHub Actions? Comment or connect — happy to help!

Comments 0 total

    Add comment