Docker
Dockerfile
Multi-architecture
ARM
AMD

Check architecture in dockerfile to get amd/arm

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When a Docker build needs different packages or binaries for amd64 and arm64, the right place to branch is usually at build time, not after the image is already running. Modern Docker builds expose target-platform variables automatically, which means a Dockerfile can choose the correct download, package, or build flag without guessing from the host machine.

The Build-Time Architecture Variables

With BuildKit and docker buildx, Docker injects several arguments that describe the build target. The most useful ones are TARGETPLATFORM, TARGETOS, TARGETARCH, and TARGETVARIANT.

A simple Dockerfile can print them like this:

dockerfile
1FROM alpine:3.20
2
3ARG TARGETPLATFORM
4ARG TARGETARCH
5ARG TARGETOS
6
7RUN echo "TARGETPLATFORM=$TARGETPLATFORM" && \
8    echo "TARGETOS=$TARGETOS" && \
9    echo "TARGETARCH=$TARGETARCH"

If you build for linux/amd64, TARGETARCH will be amd64. If you build for linux/arm64, it will be arm64.

Build with:

bash
docker buildx build --platform linux/amd64 .
docker buildx build --platform linux/arm64 .

That is the cleanest way to know which architecture the image is being built for.

Using Architecture to Choose Binaries

A very common use case is downloading the right release artifact.

dockerfile
1FROM alpine:3.20
2
3ARG TARGETARCH
4
5RUN case "$TARGETARCH" in \
6        amd64) binary_url="https://example.com/tool-linux-amd64" ;; \
7        arm64) binary_url="https://example.com/tool-linux-arm64" ;; \
8        *) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; \
9    esac && \
10    wget -O /usr/local/bin/tool "$binary_url" && \
11    chmod +x /usr/local/bin/tool

This keeps one Dockerfile usable across architectures without maintaining separate copies.

Build Platform vs Target Platform

The distinction between build platform and target platform matters. If you are using emulation or a multi-arch builder, the host machine may not match the image you are producing.

Docker also exposes BUILDPLATFORM and related variables for the machine doing the build. That lets you distinguish between the system running the builder and the system you want the image to run on.

dockerfile
1FROM --platform=$BUILDPLATFORM golang:1.24 AS builder
2
3ARG TARGETOS
4ARG TARGETARCH
5
6WORKDIR /src
7COPY . .
8RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /out/app ./cmd/app
9
10FROM alpine:3.20
11COPY --from=builder /out/app /usr/local/bin/app
12CMD ["app"]

This pattern is common in multi-stage builds for compiled languages.

Should You Use uname -m?

Inside a container, uname -m tells you about the running environment, not necessarily the image target that should shape your build logic. In simple local builds it may appear to work, but it becomes unreliable when cross-building.

For Dockerfile decisions, prefer TARGETARCH. It describes the intended image architecture directly and works consistently with buildx.

If you do need runtime detection inside the container, use it for runtime behavior, not for build branching.

Multi-Architecture Publishing

A single Dockerfile can support both architectures, and buildx can publish a manifest list that points to architecture-specific images.

bash
1docker buildx build \
2  --platform linux/amd64,linux/arm64 \
3  -t example/myapp:latest \
4  --push .

Docker clients then pull the matching image automatically on each machine.

That is usually better than manually tagging myapp-amd64 and myapp-arm64, unless you need explicit low-level control.

Common Pitfalls

A common mistake is trying to detect the architecture from the build host instead of the target image. That breaks as soon as cross-building enters the picture.

Another mistake is forgetting to declare ARG TARGETARCH before using it. Docker does not make the variable available unless the Dockerfile declares it.

Some builds also mix architecture names from different ecosystems. Docker uses values such as amd64 and arm64, while download pages may use labels such as x86_64 or aarch64. Map them carefully.

Finally, avoid duplicating entire Dockerfiles just to swap one package or binary. Use architecture arguments and keep the build logic centralized.

Summary

  • Use TARGETARCH and related build args for architecture-aware Dockerfiles.
  • Prefer build-time target variables over uname -m for branching logic.
  • Use buildx when building for amd64 and arm64 from one source.
  • Map Docker architecture names carefully to upstream release names.
  • Keep one Dockerfile and switch behavior with case or build-stage variables.

Course illustration
Course illustration

All Rights Reserved.