The More the Merrier: Multi-Arch Docker Manifests with Buildx and Artifactory

The cloud native promise to be able to “build once, deploy anywhere” is nearly fulfilled. With containerization and Docker, we can build our applications and services for any environment, and set configuration at runtime.

Well,… almost. Operating systems and apps still need to be compiled to execute on specific architecture types. Your software that’s been compiled for an AMD64 processor can’t run on an ARM-based machine, nor can one built for Linux run on Windows.

Docker addresses this need for container applications to support multi-CPU architectures with a multiple architecture (multi-arch) image. You can build images for each architecture you need to support, then bundle the set in a Docker manifest list. You can then deploy the resulting multi-arch image by its name and tag — the Docker client will automatically choose the image that matches the target’s architecture.

It’s easy to build your multi-arch images to a Docker registry in Artifactory, and manage them just like any other Docker image. We’ll show you how, and also how to promote these images through your SDLC.

The Multi-Arch Image

For our example, we want an application that we must be able to run on two processor architectures under the Linux OS: 

  1. an x86-64 environment such as your Linux desktop, 
  2. an ARM-based A1 instance on AWS EC2. 

To be able to run on either, we’ll need a multi-arch image that supports the amd64 and arm64 architectures.

Creating the Multi-Arch Image Using Buildx

To start, our DockerFile must be configured to build the example image according to the needed architecture.

ARG ARCH=
FROM ${ARCH}debian:buster-slim
 
RUN apt-get update \
&& apt-get install - y curl \
&& rm -rf /var/lib/apt/lists/*
 
ENTRYPOINT [ “curl” ]

 

If we run a docker build with this DockerFile and use a --build-arg option to set the ARCH argument, we can build a single image for each desired architecture. We would then need to build a separate manifest list (using the docker manifest command) to bundle them into a multi-arch image.

That would work, but there’s an even simpler (and preferred) way. Using the buildx, plugin for the Docker CLI, you can create a multi-arch image and push it to the Docker registry in Artifactory from a single Docker CLI command line:

$ docker buildx build \
--push \
--platform linux/amd64,linux/arm64 \
--output=type=image,push=true,registry.insecure=true \
--tag myartifactory/docker-local /multiarch-image:tag .

 

If you’re using Docker Desktop on Mac or Windows, buildx is shipped with it. If you’re on Linux, you can install buildx from GitHub.

The Multi-Arch Image in Artifactory

Here’s how the completed multiarch-image is stored in Artifactory, shown here in the docker-local Docker repository.

Manifest List

The manifest list (list.manifest.json) produced by Docker is a “manifest of manifests” for our multi-arch image. Also called a “fat manifest,” it identifies the Docker images within the set and what architectures (both OS and processor combination) each image is targeted to run on.

When the multiarch-image application is run, the Docker CLI will pull the manifest list first, then use it to select which image to pull and deploy, to match the OS and architecture of the target destination.

Architecture Images

Each of the images for supported architectures has its own tag it can be addressed by, which Artifactory creates by combining the publish tag and the architecture name. Since our example uses the publish tag “tag” then the tags for the architecture images are tag-linux-amd64 and tag-linux-arm64.

Each image also has its own manifest identifying the layers that compose it.

Promoting the Multi-Arch Image

Once your multi-arch image is in a Docker repository in Artifactory and has passed testing, you can promote the image to another Docker repository just as you would any other.

This JFrog CLI command makes a copy of the mult-arch image we created in the docker-local repository.

$ jfrog rt docker-promote --copy \
multiarch-image docker-local docker-target

 

As with any Docker image, you can also limit the promotion to a certain tag within the image. If you choose to rename the tag in the promotion, it will be renamed for each of the architectures in the multi-arch image.

$ jfrog rt docker-promote --copy \
--source-tag “latest” --target-tag “latest-new” \
multiarch-image docker-local docker-target

Best Practices Maintained

Driving your multi-arch image through your SDLC likely means more complicated testing and validation, since each supported architecture may need to be separately verified on its target platform. 

But with Artifactory’s support for multi-arch images, your best practices workflow is preserved; you can still build once and promote your immutable image through your stages of development, testing, and production.

It’s easy to give it a try. If you’re not already using Artifactory, start now with a free JFrog cloud account!