Course outline

Docker / Build evidence and production operations / Lesson 15

Multi-platform images and cross-compilation

Distinguish an image index, a platform-specific manifest, a builder architecture, and a runtime architecture.

About 4 min readContent reviewed
On this page

Lesson goals

  • Explain native builds, emulation, and cross-compilation tradeoffs.
  • Review a two-platform Go recipe and verify platform identity without installing host emulation.

One reference can describe several platform artifacts

A multi-platform image reference can resolve to an OCI image index or equivalent manifest list that points to platform-specific manifests. Each child can have different layers and configuration. The runtime selects a compatible platform when supported. An index digest and a child manifest digest identify different content objects. Record the requested operating system and architecture alongside the digest rather than assuming a single tag means one universal executable.

Choose the build strategy from workload evidence

Native builders avoid instruction emulation for their own platform but require suitable machines and trusted coordination. Emulation can make a foreign platform build possible yet be substantially slower for compilation and compression. Cross-compilation runs a native toolchain that emits another target's executable, when the language and dependencies support it. None of these strategies proves runtime correctness; architecture-specific behavior, libraries, and kernel requirements still need testing on representative targets.

Separate BUILDPLATFORM from TARGETPLATFORM

The following recipe reuses the complete Go source and module from the multi-stage lesson. The compiler stage runs for BUILDPLATFORM while TARGETOS and TARGETARCH select the emitted executable. This example intentionally targets linux/amd64 and linux/arm64 with CGO disabled; it does not promise that arbitrary C libraries or every architecture variant cross-compile without extra configuration. Automatic platform arguments must be declared in the stage where RUN consumes them.

dockerfile Cross-compile the explicit fixture
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:1.26-alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
COPY go.mod main.go ./
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \
    go build -trimpath -o /out/parcel ./
FROM scratch
COPY --from=build /out/parcel /parcel
USER 65532:65532
EXPOSE 8080
ENTRYPOINT ["/parcel"]

For an arm64 target, GOARCH receives arm64 even when the compiler runs on an amd64 builder. The runtime receives the matching binary only. The base tag remains mutable teaching input; release pinning and target tests remain necessary. No builder, emulator, or host registration is created by this lesson.

Choose a supported artifact destination

Builder driver and image-store capabilities determine how multi-platform results can be loaded, pushed, or exported. A classic image store and a containerd-backed store do not have identical behavior. An OCI archive can represent a reviewed artifact without requiring a deployment, but its creation still performs a real build when authorized. Registry publication adds authentication and retention concerns. Decide the consumer and export format before choosing flags, and never assume a successful build log means a local runnable image was loaded.

bash Inspect platform metadata and review an OCI export plan
docker buildx imagetools inspect python:3.13-slim
# Review-only build plan, not executed:
docker buildx build --platform linux/amd64,linux/arm64 \
  --tag parcel-api:review --output type=oci,dest=parcel-review.tar .

imagetools reads registry metadata and can list platform descriptors. The second command would build and write an archive; it is explicitly not executed and requires an approved builder and the complete source context. No fixed manifest digests, build timing, archive contents, or runtime success are fabricated.

Test the exact child artifact on its target

Check manifest platform descriptors, executable architecture, expected runtime files, and application behavior on each intended target. Emulation success is useful but may miss performance and platform-specific issues on real hardware. A shell script with a missing interpreter can resemble an architecture failure, so inspect entrypoint format before assigning a cause. Preserve the index-to-child mapping with test evidence, ensuring that release promotion uses the same reviewed content rather than rebuilding another mutable tag.

Common errors and fixes

exec format error.

Why it happens
The executable may target the wrong architecture, or its format/interpreter contract is invalid.
How to fix it
Inspect platform metadata and entrypoint bytes before selecting a compatible artifact.
Prevent it next time
Test each published platform child on a representative target.

A multi-platform build is absent from the expected local image store.

Why it happens
The chosen builder exported elsewhere or the store lacks the expected loading support.
How to fix it
Review builder driver, output flags, and image-store capability.
Prevent it next time
State artifact destination explicitly in build plans.

Cross-compilation unexpectedly uses the builder architecture.

Why it happens
Target arguments were not declared or passed to the compiler in the build stage.
How to fix it
Declare and consume TARGETOS and TARGETARCH at the correct stage.
Prevent it next time
Verify binary architecture before publishing descriptors.

Check your understanding

1. Why can two platform children share a tag but have different digests?

Show worked solution

The tag can identify an index containing separate manifests for each platform. Different binaries and layers naturally produce different child content identities. The index describes their relationship; equality of friendly names is not evidence that the underlying executable bytes are interchangeable.

2. Does this recipe require installing privileged host emulation to explain arm64 output?

Show worked solution

No. The illustrated strategy uses a native Go compiler with explicit cross-compilation targets for a standard-library, CGO-disabled program. Actual builder support still needs verification, but no host emulation installation or privileged container is authorized or executed by this course.

Key takeaways

  • Record index identity, child identity, target platform, and export destination.
  • Cross-compilation and emulation are different strategies with different evidence needs.

Official references