Skip to content
Latchkey

How to Build and Push a Multi-Arch Docker Image in CI

QEMU plus Buildx lets one CI step emit a manifest list that serves the right image to each architecture.

Set up QEMU for emulation and Buildx as the builder, then pass platforms: linux/amd64,linux/arm64 to docker/build-push-action. The registry receives a manifest list, and clients pull the matching arch automatically.

Steps

  • Set up QEMU with docker/setup-qemu-action so the runner can emulate other architectures.
  • Set up Buildx with docker/setup-buildx-action.
  • Log in to the registry, then run build-push-action with a comma-separated platforms: list.

Workflow

.github/workflows/docker.yml
jobs:
  image:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-qemu-action@v3
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v6
        with:
          push: true
          platforms: linux/amd64,linux/arm64
          tags: ghcr.io/${{ github.repository }}:latest

Gotchas

  • Emulated arm64 builds run several times slower than native; cache layers to offset it.
  • A multi-platform build cannot use load: true (the daemon holds one arch only); push to a registry instead.
  • Latchkey offers native arm64 runners, so multi-arch builds avoid QEMU emulation overhead.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →