Building Multi-Platform Container Images with Docker Buildx
Tags: docker, container, buildx, kcd
Published: 2023-05-22 13:39:36

_Disclaimer: This article was originally published on [Medium.com](https://navinprasadk.medium.com/building-multi-platform-container-images-with-docker-buildx-c2d051d5ca2c) and has been reposted here on Dev.to_

If your containers are intended to be used on multiple platforms, then building multi-platform container images can be very useful. Building multi-platform container images allows you to create a single image that can be run on different types of systems, such as Intel, ARM, and AMD. This can save you time and effort because you don’t need to build separate container images for each platform, and it can also make it easier to distribute your container images.

**Using Docker Buildx**
[Docker Buildx](https://github.com/docker/buildx) is a Docker CLI plugin that extends the docker build command with the ability to build container images for multiple platforms and architectures at the same time. It is an experimental feature of Docker version 18.09. Using Docker Buildx, you can build and push container images to multiple platforms with a single command, allowing you to create cross-platform container images that can be used on different types of systems.

**How Docker Buildx Works**
Docker Buildx works by creating a build "context" that includes the Dockerfile, source code, and build context, and then building the container images for all the specified platforms at the same time.

**Steps to Build Multi-Platform Docker Images and Push them to Docker Hub**

**Step 1: Install Docker Buildx**
To install Docker Buildx, run the following command in the terminal: 
`docker buildx install
`
**Step 2: Enable Experimental Features**
To enable experimental features in Docker, add the following line to your Docker configuration file (usually located at ~/.docker/config.json):** "experimental": "enabled"**. Restart Docker to apply the changes.

**Step 3: Create a New Docker Buildx Builder**
To create a new Docker Buildx builder, run the following command: `docker buildx create - name mybuilder`
This will create a new builder with the default settings.

**Step 4: Switch to the New Builder**
To switch to the new builder, run the following command: `docker buildx use mybuilder`
This will activate the new builder for all subsequent Docker commands.

**Step 5: Check Your Builder's Capabilities**
Run the following command to check your builder's capability of building multi-platform container images: `docker buildx inspect - bootstrap`

`docker buildx inspect --bootstrap
Name:   mybuilder
Driver: docker-container
Nodes:
Name:      mybuilder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Buildkit:  v0.11.3
Platforms: linux/arm64, linux/amd64, linux/amd64/v2`

Note that the image you are pulling from must also support the architectures you plan to target. This can be checked using: `docker buildx imagetools inspect alpine:3.16`

`docker buildx imagetools inspect alpine:3.16
Name:      docker.io/library/alpine:3.16
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:1bd67c81e4ad4b8f4a5c1c914d7985336f130e5cefb3e323654fd09d6bcdbbe2
Manifests:
  Name:      docker.io/library/alpine:3.16@sha256:0b29a7f4d42d6b5d6433ea91322903900e81b95d47d97d909a6e388e840f4f4a
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/amd64             
  Name:      docker.io/library/alpine:3.16@sha256:ed4d840b601f052e9d1c3bb843ad11e904d0265936c90c18e8e7bf6dc2f80d41
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm/v6        
  Name:      docker.io/library/alpine:3.16@sha256:32c3aacc36c2ceb104f43efbd7cf1c0732cf798e088b784b7c02cee27498b0a8
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm/v7            
  Name:      docker.io/library/alpine:3.16@sha256:3b37be168bb81cf274793cebd596b4a023bdbca6f3b5bc3dfe8974e569b74feb
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm64/v8         
  Name:      docker.io/library/alpine:3.16@sha256:abc178f562a2827f068bd0e60f48d998179dcd7130cc5036a287e1716536c306
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/386     
  Name:      docker.io/library/alpine:3.16@sha256:e6a8ba98c4be90c07b31be6e3315beeaa1fd5269ac215e581babef640a34ed0b
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/ppc64le
  Name:      docker.io/library/alpine:3.16@sha256:1394c85a9984cb03d369381672a1767378b49d8701adfc6337258756052b2eeb
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/s390`

**Step 6: Create a Dockerfile**
Create a Dockerfile with the following content:

`# syntax=docker/dockerfile:1
FROM alpine:3.16 
RUN apk add curl`

**Step 7: Log in to [Docker Hub](https://hub.docker.com/)**
Log in to Docker Hub using the following command: `docker login`
Enter your Docker Hub username and password when prompted.

**Step 8: Build, Tag and Push Your Docker Image**
Build and tag your Docker image using the newly created builder and specify the desired platforms. For example, to build and tag an image for Intel x86_64, AMD64, and ARM64 architectures, you can use the following command: 
`docker buildx build - platform linux/amd64,linux/arm64,linux/386 -t your-dockerhub-username/your-image-name:tag.`

`docker buildx build --platform linux/amd64,linux/arm64 -t navinprasadk/apkaddcurl:v2 . --push`

You can specify additional platforms for your image by adding them to the `- platform `option.
Add the `- push command` to the above command to instruct the docker CLI to push the Docker image to Docker Hub.

`docker buildx build --platform linux/amd64,linux/arm64 -t navinprasadk/apkaddcurl:v2 . --push
[+] Building 22.5s (12/12) FINISHED                                                                                                                                                                          
 => [internal] load build definition from Dockerfile                                                                                                                                                    0.0s
 => => transferring dockerfile: 99B                                                                                                                                                                     0.0s
 => [internal] load .dockerignore                                                                                                                                                                       0.0s
 => => transferring context: 2B                                                                                                                                                                         0.0s
 => resolve image config for docker.io/docker/dockerfile:1                                                                                                                                              0.8s
 => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14                                                                         0.0s
 => => resolve docker.io/docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14                                                                                    0.0s
 => [linux/amd64 internal] load metadata for docker.io/library/alpine:3.16                                                                                                                              0.3s
 => [linux/arm64 internal] load metadata for docker.io/library/alpine:3.16                                                                                                                              0.6s
 => [linux/arm64 1/2] FROM docker.io/library/alpine:3.16@sha256:1bd67c81e4ad4b8f4a5c1c914d7985336f130e5cefb3e323654fd09d6bcdbbe2                                                                        0.0s
 => => resolve docker.io/library/alpine:3.16@sha256:1bd67c81e4ad4b8f4a5c1c914d7985336f130e5cefb3e323654fd09d6bcdbbe2                                                                                    0.0s
 => [linux/amd64 1/2] FROM docker.io/library/alpine:3.16@sha256:1bd67c81e4ad4b8f4a5c1c914d7985336f130e5cefb3e323654fd09d6bcdbbe2                                                                        0.0s
 => => resolve docker.io/library/alpine:3.16@sha256:1bd67c81e4ad4b8f4a5c1c914d7985336f130e5cefb3e323654fd09d6bcdbbe2                                                                                    0.0s
 => CACHED [linux/amd64 2/2] RUN apk add curl                                                                                                                                                           0.0s
 => CACHED [linux/arm64 2/2] RUN apk add curl                                                                                                                                                           0.0s
 => exporting to image                                                                                                                                                                                 20.9s
 => => exporting layers                                                                                                                                                                                 0.1s
 => => exporting manifest sha256:403248829517c743afe783d3931166e800d7d716f7d0d210a9381ca1c45318df                                                                                                       0.0s
 => => exporting config sha256:cc19d353d0f23f8a8f92e2a32cc7d0f5aee98d2352b5fdeb34c06b17600b5c69                                                                                                         0.0s
 => => exporting manifest sha256:595145e572854ce6f2107e012c69be2eb4e148d7759a7535f9325d8b49ed1300                                                                                                       0.0s
 => => exporting config sha256:af6a49b540831ee553433675b3d38c100991995c3d82b5074a5a2d6d931208a9                                                                                                         0.0s
 => => exporting manifest list sha256:55b1de08ad830205a77330b52e3d32740839cc4a6a88e033bdcd954192e749b2                                                                                                  0.0s
 => => pushing layers                                                                                                                                                                                  18.8s
 => => pushing manifest for docker.io/navinprasadk/apkaddcurl:v2@sha256:55b1de08ad830205a77330b52e3d32740839cc4a6a88e033bdcd954192e749b2                                                                1.9s
 => [auth] navinprasadk/apkaddcurl:pull,push token for registry-1.docker.io`

**Conclusion**
Overall, Docker Buildx is a powerful tool for building multi-platform container images. It can be handy if you need your container images to run on multiple platforms or if you want to take advantage of cloud platforms that support running Docker containers on a variety of platforms. By following the steps in this tutorial, you can easily create cross-platform container images that can be used on different types of systems.