KhueApps
Home/DevOps/Fix Docker multi-arch mismatches and correct --platform use

Fix Docker multi-arch mismatches and correct --platform use

Last updated: October 07, 2025

Overview

Multi-arch images bundle variants for different CPU architectures (amd64, arm64, arm/v7, etc.). Mismatches cause errors like:

  • no matching manifest for linux/amd64 in the manifest list entries
  • exec format error

This guide shows how to diagnose platform issues and correctly select platforms with --platform across docker run, pull, buildx, and Compose.

Quickstart

  1. Check your host arch: uname -m (amd64 is x86_64, arm64 is aarch64).
  2. Inspect image platforms: docker buildx imagetools inspect IMAGE.
  3. Run with explicit platform if needed: docker run --platform linux/amd64 IMAGE.
  4. For builds, use buildx: docker buildx build --platform linux/amd64,linux/arm64 ...
  5. In Compose, set platform: linux/amd64 or linux/arm64 per service.
  6. If emulation is required, install binfmt/qemu and expect slower performance.

Minimal Working Example

Goal: run the same image as amd64 and arm64 on any host and confirm the selected platform inside the container.

Dockerfile:

# Dockerfile
FROM alpine:3.19
CMD ["sh", "-c", "uname -m && cat /etc/alpine-release"]

Build multi-arch and push to a registry (requires BuildKit/buildx):

# 1) Ensure buildx is active
docker buildx create --use --name multi || docker buildx use multi

# 2) Enable emulation (if building for a non-native arch)
docker run --privileged --rm tonistiigi/binfmt --install all

# 3) Build and push a multi-arch image (replace YOURUSER)
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t YOURUSER/alpine-uname:demo \
  --push .

Run explicitly as each platform (works even on the opposite host if emulation is installed):

# Runs arm64 variant
docker run --rm --platform linux/arm64 YOURUSER/alpine-uname:demo
# Runs amd64 variant
docker run --rm --platform linux/amd64 YOURUSER/alpine-uname:demo

You should see uname -m output differ (e.g., aarch64 vs x86_64).

Diagnose a multi-arch mismatch

  • Identify your host architecture:
uname -m
  • Inspect available platforms for an image:
# Buildx inspector (concise and multi-arch aware)
docker buildx imagetools inspect nginx:alpine

# Or the classic manifest inspector
docker manifest inspect --verbose nginx:alpine | jq '.manifests[].platform'
  • Typical symptoms:
    • no matching manifest: the image tag does not include your target platform.
    • exec format error: you pulled the wrong arch variant and the kernel cannot execute it.

Select a platform for run and pull

  • Run for a specific platform:
docker run --rm --platform linux/amd64 nginx:alpine
  • Pull a specific platform (useful for offline or CI):
docker pull --platform linux/arm64 nginx:alpine
  • Set a temporary default for the session:
export DOCKER_DEFAULT_PLATFORM=linux/amd64

Note: On macOS and Windows, Docker always runs Linux containers; pick linux/amd64 or linux/arm64 accordingly.

Compose: set platform per service

# docker-compose.yml
version: "3.8"
services:
  web:
    image: nginx:alpine
    platform: linux/amd64
    ports:
      - "8080:80"

Apply with:

docker compose up --pull=always --force-recreate

Build correctly with buildx and Dockerfile args

  • Cross-build with buildx:
# Build but load only one arch into the local docker images store
docker buildx build --platform linux/amd64 -t app:test --load .

# Build multi-arch and push
docker buildx build --platform linux/amd64,linux/arm64 -t YOURUSER/app:multi --push .
  • Use automatic build args for cross-builds in your Dockerfile:
# Dockerfile (multi-arch aware)
# BuildKit provides these at build time: BUILDPLATFORM, TARGETPLATFORM, TARGETOS, TARGETARCH
ARG TARGETPLATFORM
ARG TARGETARCH
FROM --platform=$TARGETPLATFORM alpine:3.19 AS base
RUN echo "Building for $TARGETPLATFORM ($TARGETARCH)"
CMD ["sh", "-lc", "echo runtime arch: $(uname -m)"]

This ensures the correct base image variant is selected during multi-arch builds.

Common fixes by scenario

  • Error: no matching manifest for linux/amd64
    • Pick another tag that includes linux/amd64, or select a platform present in the manifest list.
    • Verify platforms with docker buildx imagetools inspect IMAGE:TAG.
  • Error: exec format error
    • Pull/run with the right platform (docker run --platform ...).
    • Remove the wrong-arch image and re-pull: docker rmi IMAGE && docker pull --platform TARGET ...
  • CI on arm64 runners pulling amd64 images
    • Set DOCKER_DEFAULT_PLATFORM=linux/amd64 for steps that need x86.
    • Use buildx with --platform linux/amd64 or multi-arch as needed.
  • Apple Silicon host running x86-only tools
    • Use --platform linux/amd64 or Compose platform: linux/amd64. Expect emulation overhead.

Pitfalls

  • Not all tags are multi-arch. Pin tags known to include your target platform.
  • --platform on docker build requires BuildKit; prefer buildx for multi-arch.
  • Changing --platform pulls different layers; your cache may miss. Use registry cache exports when possible.
  • Emulation requires binfmt to be installed; some environments disable it.
  • In Compose, platform affects run images; building multi-arch images still requires buildx and --platform.
  • Container OS is still Linux; do not use darwin/amd64 or windows/amd64 with Linux images.

Performance notes

  • Emulated execution (e.g., running linux/amd64 on arm64 via QEMU) is slower—expect 2–5x overhead for CPU-bound tasks.
  • Prefer native architecture for long-running or performance-sensitive workloads.
  • For builds, offload to a builder node with native CPUs for target platforms, or use buildx with multiple nodes to parallelize.
  • Cache wisely: use --cache-to/--cache-from or registry-backed cache to avoid rebuilding per-arch layers repeatedly.

Tiny FAQ

  • How do I see which platforms an image supports?
    • docker buildx imagetools inspect IMAGE:TAG
  • What values can I use with --platform?
    • Common: linux/amd64, linux/arm64, linux/arm/v7, linux/s390x, linux/ppc64le.
  • I set --platform but Docker still chose another variant during build.
    • Use buildx and ensure FROM uses --platform=$TARGETPLATFORM. Classic docker build may ignore multi-arch nuances without BuildKit.
  • Do I need to push to create a multi-arch image?
    • Yes, manifest lists are registry objects. Use buildx --push to publish combined manifests.
  • Can I make a global default?
    • Export DOCKER_DEFAULT_PLATFORM in your shell or CI environment.

Series: Docker

DevOps