This guide shows how to build multiarch Docker containers for Rust applications using cargo zigbuild for cross-compilation and Docker build commands for architecture-specific or multiarch container images. Based on the example for Building a Rust API with Rocket and JWT Authentication, this guide provides the next steps.
Cross-Compiling with Zigbuild
Install cross-compilation targets for ARM64 and x86_64:
# Install rustup targets for arm and x86
$ > rustup target add aarch64-unknown-linux-gnu
$ > rustup target add x86_64-unknown-linux-gnu
Build release binaries for both architectures using cargo zigbuild:
# Build architecture binaries for linux
$ > cargo zigbuild --release --target x86_64-unknown-linux-gnu
$ > cargo zigbuild --release --target aarch64-unknown-linux-gnu
The zigbuild command handles cross-compilation toolchain setup automatically. Binaries are created in target/x86_64-unknown-linux-gnu/release/ and target/aarch64-unknown-linux-gnu/release/ respectively.
Dockerfile for Multiarch Builds
Use a single Dockerfile that selects the appropriate pre-built binary based on the target architecture:
FROM amazonlinux:2023 AS base
ARG TARGETARCH
RUN --mount=type=bind,source=./target/aarch64-unknown-linux-gnu/release,target=/mnt/arm \
--mount=type=bind,source=./target/x86_64-unknown-linux-gnu/release,target=/mnt/x86 \
if [ "$TARGETARCH" = "arm64" ] && [ -f /mnt/arm/rocket-example ]; then \
cp /mnt/arm/rocket-example /usr/local/bin/rocket-example; \
elif [ "$TARGETARCH" != "arm64" ] && [ -f /mnt/x86/rocket-example ]; then \
cp /mnt/x86/rocket-example /usr/local/bin/rocket-example; \
else \
echo "Error: No service binary found for architecture!" >&2; \
exit 1; \
fi && \
chmod +x /usr/local/bin/rocket-example
# Default version
FROM base AS default
ENV ROCKET_LOG_LEVEL=debug
ENV ROCKET_ADDRESS=0.0.0.0
ENV ROCKET_PORT=3000
CMD ["rocket-example"]
The Dockerfile uses Docker’s ARG TARGETARCH to detect the target architecture at build time. Bind mounts access the pre-built binaries from the local target/ directory and copy the appropriate binary based on the architecture. This ensures each container only contains the binary for its architecture, avoiding bloated container sizes.
Building Architecture-Specific Containers
Build containers for specific architectures using the --platform flag:
# Build Docker for ARM64
$ > docker build \
--platform linux/arm64 \
-f Dockerfile . \
-t rocket-example:latest-arm64
# Build Docker for x86_64
$ > docker build \
--platform linux/amd64 \
-f Dockerfile . \
-t rocket-example:latest-amd64
Using architecture-specific tags like latest-arm64 and latest-amd64 ensures each container only contains the binary for its architecture, avoiding bloated container sizes.
Building Multiarch Containers with Buildx
Build for multiple architectures in a single command using Docker Buildx:
$ > docker buildx build --platform linux/amd64,linux/arm64 . \
-t rocket-example:latest
This creates a generic latest tag with a manifest list that includes both architectures. Docker automatically selects the correct architecture when pulling or running the container.