Build Multi-Architecture Docker Images with Buildx and GitHub Actions
Building Cross-Platform Docker Images
Cross-platform Docker builds enable creating images for multiple architectures (linux/amd64, linux/arm64) from a single Dockerfile. Docker Buildx provides the necessary tooling for multi-platform builds across local environments and CI/CD pipelines.
Prerequisites
- Docker Desktop (includes Buildx) or Docker Engine 19.03+
- QEMU (required for building non-native architectures locally)
- Docker Hub or compatible container registry for pushing multi-arch images
Platform-Aware Dockerfiles
Use automatic platform ARGs to conditionally execute instructions based on target architecture:
FROM alpine:latest
ARG TARGETPLATFORM
ARG TARGETARCH
RUN if [ "$TARGETARCH" = "amd64" ]; then \
apk add --no-cache some-amd64-package; \
elif [ "$TARGETARCH" = "arm64" ]; then \
apk add --no-cache some-arm64-package; \
fi
RUN echo "Building for $TARGETPLATFORM"
TARGETPLATFORM is automatically injected by Buildx during multi-platform builds.
Local Setup (macOS & Windows)
Enable Buildx Builder
Docker Desktop includes Buildx, but you must create a builder instance:
docker buildx create --use --name multiarch-builder
docker buildx inspect --bootstrap
The --bootstrap flag initializes the builder and ensures the node is reachable.
Build Multi-Platform Images
Build for multiple architectures using the --platform flag:
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t your-registry/your-image:latest \
--push \
.
The --push flag is required for multi-arch builds since the local daemon cannot load multi-platform manifests directly.
Local Testing with --load
For single-platform local testing, use --load to load the image into your local Docker daemon:
docker buildx build \
--platform linux/amd64 \
-t your-registry/your-image:test \
--load \
.
The --load flag only works with a single platform. Multi-platform builds must use --push.
GitHub Actions
Complete Workflow
Create .github/workflows/docker-build.yml:
name: Build Multi-Platform Images
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/${{ github.repository }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
This example uses GitHub Container Registry (ghcr.io). For Docker Hub, change registry to docker.io and use DOCKER_USERNAME/DOCKER_PASSWORD secrets.
Key Actions Explained
docker/setup-qemu-action@v3: Enables QEMU emulation for non-native architecturesdocker/setup-buildx-action@v3: Configures Buildx builder with multi-platform supportdocker/build-push-action@v5: Executes the build with theplatformsparametercache-from/cache-to: Uses GitHub Actions cache to store and retrieve build layers
Distributed Builds (Advanced)
For large images, distribute builds across multiple runners to reduce total build time. Each runner builds a single platform, then manifests are merged. The single-step multi-platform build shown above is preferred for most use cases.
jobs:
build:
strategy:
matrix:
include:
- platform: linux/amd64
tag: linux-amd64
- platform: linux/arm64
tag: linux-arm64
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build for ${{ matrix.platform }}
uses: docker/build-push-action@v5
with:
context: .
platforms: ${{ matrix.platform }}
push: true
tags: ghcr.io/${{ github.repository }}:latest-${{ matrix.tag }}
cache-from: type=gha
cache-to: type=gha,mode=max
merge:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest
run: |
docker buildx imagetools create \
-t ghcr.io/${{ github.repository }}:latest \
ghcr.io/${{ github.repository }}:latest-linux-amd64 \
ghcr.io/${{ github.repository }}:latest-linux-arm64
The merge job runs on a fresh runner and requires its own Buildx setup and registry login to create and push the manifest.
Verification
Inspect the multi-platform manifest:
docker buildx imagetools inspect your-registry/your-image:latest
This displays the manifest list showing all supported platforms.
Runtime Testing
Test execution on specific architectures using QEMU emulation:
# Test on ARM64
docker run --rm --platform linux/arm64 your-registry/your-image:latest uname -m
# Test on AMD64
docker run --rm --platform linux/amd64 your-registry/your-image:latest uname -m
Verify the output matches the expected architecture (aarch64 for ARM64, x86_64 for AMD64).
Share this Guide:
More Guides
Agentic Workflows: Building Self-Correcting Loops with LangGraph and CrewAI State Machines
Build production-ready AI agents that iteratively improve their outputs through automated feedback loops, combining LangGraph's state machine architecture with CrewAI's multi-agent orchestration for robust, self-correcting workflows.
14 min readBun Runtime Migration: Porting High-Traffic Node.js APIs with Native APIs and SQLite
Learn how to migrate high-traffic Node.js APIs to Bun for 4× HTTP throughput and 3.8× database performance gains using native APIs and bun:sqlite.
10 min readDeno 2.0 Workspaces: Build Monorepos with JSR Packages and TypeScript-First Development
Learn how to configure Deno 2.0 workspaces for monorepo management, publish TypeScript packages to JSR, and automate releases with OIDC-authenticated CI/CD pipelines.
7 min readGleam on BEAM: Building Type-Safe, Fault-Tolerant Distributed Systems
Learn how Gleam combines Hindley-Milner type inference with Erlang's actor-based concurrency model to build systems that are both compile-time safe and runtime fault-tolerant. Covers OTP integration, supervision trees, and seamless interoperability with the BEAM ecosystem.
5 min readHono Edge Framework: Build Ultra-Fast APIs for Cloudflare Workers and Bun
Master Hono's zero-dependency web framework to build low-latency edge APIs that deploy seamlessly across Cloudflare Workers, Bun, and other JavaScript runtimes. Learn routing, middleware, validation, and real-time streaming patterns optimized for edge computing.
6 min readContinue Reading
Agentic Workflows: Building Self-Correcting Loops with LangGraph and CrewAI State Machines
Build production-ready AI agents that iteratively improve their outputs through automated feedback loops, combining LangGraph's state machine architecture with CrewAI's multi-agent orchestration for robust, self-correcting workflows.
14 min readBun Runtime Migration: Porting High-Traffic Node.js APIs with Native APIs and SQLite
Learn how to migrate high-traffic Node.js APIs to Bun for 4× HTTP throughput and 3.8× database performance gains using native APIs and bun:sqlite.
10 min readDeno 2.0 Workspaces: Build Monorepos with JSR Packages and TypeScript-First Development
Learn how to configure Deno 2.0 workspaces for monorepo management, publish TypeScript packages to JSR, and automate releases with OIDC-authenticated CI/CD pipelines.
7 min readShip Faster. Ship Safer.
Join thousands of engineering teams using MatterAI to autonomously build, review, and deploy code with enterprise-grade precision.
