Skip to main content

How to specify the CPU architecture when pulling images with Podman

If you're building multi-architecture solutions, you need to know how container image architectures work, how to pull them, and how to run containers on different systems using Podman.
Image
Green CPU on a motherboard

Photo by Jeremy Waterhouse from Pexels

Podman is a daemonless engine for developing, managing, and running Open Container Initiative (OCI)-compliant containers. This is the fifth and final article in a series about using Podman. The series provides content on basic container administration using Podman by manipulating different commands and parameters.

Before reading this article, make sure you've read the first four parts:

  1. Create fast, easy, and repeatable containers with Podman and shell scripts
  2. How to use Podman to get information about your containers
  3. How Podman can extract a container's external IP address
  4. How to update container images with Podman

This article demonstrates how to specify a chip architecture when pulling images. This is important when running containers in architectures other than x86_64, such as Arm, Arm64, mips64le, ppc64le, s390x, and others. To follow along with this article, pull the container images I specified in the Setting things up section of the first article in this series.

Inspecting images and manifests before pulling

Before proceeding with pulling images with different architectures, I'll review how to check the architecture of a given image and the architecture options its manifest provides. These are the current images I pulled to my host machine in the previous articles:

$ podman image ls
REPOSITORY                   TAG         IMAGE ID      CREATED        SIZE
docker.io/library/httpd      latest      dabbfbe0c57b  2 months ago   148 MB
docker.io/library/wordpress  latest      054741915cf1  3 months ago   629 MB
docker.io/library/mysql      latest      bbf6571db497  3 months ago   521 MB
<none>                       <none>      ea28e1b82f31  3 months ago   148 MB
k8s.gcr.io/pause             3.5         ed210e3e4a5b  11 months ago  690 kB

By default, the podman pull command pulls an image with the architecture according to the target host machine. In my scenario, it pulled all my images with the Amd64 architecture:

$ podman image inspect docker.io/library/{httpd,wordpress,mysql} | jq -r '.[] | .Architecture'
amd64
amd64
amd64

But how many architecture options do these images give me if I want to pull a different architecture? Inspection in the image manifest helps me find out:

$ podman manifest inspect docker.io/library/httpd | grep architecture
                "architecture": "amd64",
                "architecture": "arm",
                "architecture": "arm",
                "architecture": "arm64",
                "architecture": "386",
                "architecture": "mips64le",
                "architecture": "ppc64le",
                "architecture": "s390x",

$ podman manifest inspect docker.io/library/wordpress | grep architecture
                "architecture": "amd64",
                "architecture": "arm",
                "architecture": "arm",
                "architecture": "arm64",
                "architecture": "386",
                "architecture": "mips64le",
                "architecture": "ppc64le",
                "architecture": "s390x",

$ podman manifest inspect docker.io/library/mysql | grep architecture
                "architecture": "amd64",

As you can see, two of my three pulled images (httpd and wordpress) have eight different architecture options, but one of them (mysql) has only one architecture option. That doesn't mean this image doesn't have other architecture options, but for this specific manifest, it doesn't. However, you can find other repos for the same image in your target registry that give you other architecture options (for example, check the supported architectures for the official MySQL image in the Docker Hub page).

[ Learn about Podman 4.0's new network stack: What you need to know. ]

So, given this information, say I'm running two different systems, each one with a different CPU architecture: one with x86_64 and another one with AArch64. How can I pull an image of a specific architecture to each of these systems? Can I pull a different image architecture of the target host machine and run a container with it? Find out in the next section.

Specifying arch when pulling images in an x86_64 system

To demonstrate, I've created another host machine with an AArch64 architecture. This way, I can show how a container with a different image architecture behaves in each one. For this first demo, I'll use the host machine I created for the first article; it is running with x86_64 architecture:

$ uname -a
Linux fedora.example.local 5.16.11-200.fc35.x86_64 #1 SMP PREEMPT Wed Feb 23 17:08:49 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

To pull images, use the command that you've been running since the beginning of this series: podman pull. Check its options:

$ podman pull --help
Pull an image from a registry

Description:
  Pulls an image from a registry and stores it locally.

  An image can be pulled by tag or digest. If a tag is not specified, the image with the 'latest' tag is pulled.

Usage:
  podman pull [options] IMAGE [IMAGE...]

Examples:
  podman pull imageName
  podman pull fedora:latest

Options:
      --all-tags                All tagged images in the repository will be pulled
      --arch ARCH               Use ARCH instead of the architecture of the machine for choosing images
      --authfile string         Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override
      --cert-dir Pathname       Pathname of a directory containing TLS certificates and keys
      --creds Credentials       Credentials (USERNAME:PASSWORD) to use for authenticating to a registry
      --disable-content-trust   This is a Docker specific option and is a NOOP
      --os OS                   Use OS instead of the running OS for choosing images
      --platform string         Specify the platform for selecting the image.  (Conflicts with arch and os)
  -q, --quiet                   Suppress output information when pulling images
      --tls-verify              Require HTTPS and verify certificates when contacting registries (default true)
      --variant string          Use VARIANT instead of the running architecture variant for choosing images

Note there are three different yet very similar parameters: --arch ARCH, --platform string, and --variant string.

The main difference between them is that with the platform parameter, you can specify an operating system or architecture for the image that's different from the host machine (such as "windows" as the OS), while with arch, you're only specifying the architecture (that's what you want here), and with variant you're specifying the variant inside the given architecture (for example, arm/v5, arm/v7, etc.).

Now I'll demonstrate what happens when you try to pull an image with an architecture (using the --arch parameter) that is not specified in the image's manifest. This test uses the mysql image:

$ podman pull --arch=arm64 docker.io/library/mysql
Trying to pull docker.io/library/mysql:latest...
Error: choosing an image from manifest list docker://mysql:latest: no image found in manifest list for architecture arm64, variant "", OS linux

It won't work. But here's what happens if you try to do the same thing but using a valid arch from the provided image repo and manifest:

$ podman pull --arch=arm docker.io/library/httpd
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
Copying blob 43d17a883cdc done  
Copying blob c2ff343d5fd2 done  
Copying blob 6a6e631a1e74 done  
Copying blob 071a8f3a328f done  
Copying blob 59dbb2ac3829 done  
Copying config 5c243f19b0 done  
Writing manifest to image destination
Storing signatures
5c243f19b0c7a9b18d7d3bebf80054b594798361ddbab222fcafa6522cf2e87b

$ podman image ls
REPOSITORY                   TAG         IMAGE ID      CREATED        SIZE
docker.io/library/httpd      latest      5c243f19b0c7  6 days ago     116 MB
<none>                       <none>      dabbfbe0c57b  2 months ago   148 MB
docker.io/library/wordpress  latest      054741915cf1  3 months ago   629 MB
docker.io/library/mysql      latest      bbf6571db497  3 months ago   521 MB
<none>                       <none>      ea28e1b82f31  3 months ago   148 MB
k8s.gcr.io/pause             3.5         ed210e3e4a5b  11 months ago  690 kB

It works! Pulling an image with an Arm arch, even when running an x86_64 host machine, is not a problem. You can check the other images (wordpress and mysql) and compare them to the httpd image to see that the current pulled image is now defaulting to the Arm arch:

$ podman image inspect docker.io/library/{httpd,wordpress,mysql} | jq -r '.[] | .Architecture'
arm
amd64
amd64

If you want to change the default pulled image for httpd, you can simply run the podman pull command again but specify the new arch that you want, for example, Arm64:

$ podman pull --arch=arm64 docker.io/library/httpd
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
Copying blob 5ba01719dd76 done  
Copying blob 0e1e146c1fe7 done  
Copying blob d2d2092da38e done  
Copying blob 14e615a0c8e4 done  
Copying blob 279a020076a7 done  
Copying config c7469bac36 done  
Writing manifest to image destination
Storing signatures
c7469bac360343c88158b2bf384f4521fa0590478c99e077ab4ec2f73b8c5316

$ podman image ls
REPOSITORY                   TAG         IMAGE ID      CREATED        SIZE
docker.io/library/httpd      latest      c7469bac3603  5 days ago     141 MB
<none>                       <none>      5c243f19b0c7  6 days ago     116 MB
<none>                       <none>      dabbfbe0c57b  2 months ago   148 MB
docker.io/library/wordpress  latest      054741915cf1  3 months ago   629 MB
docker.io/library/mysql      latest      bbf6571db497  3 months ago   521 MB
<none>                       <none>      ea28e1b82f31  3 months ago   148 MB
k8s.gcr.io/pause             3.5         ed210e3e4a5b  11 months ago  690 kB

$ podman image inspect docker.io/library/{httpd,wordpress,mysql} | jq -r '.[] | .Architecture'
arm64
amd64
amd64

The other httpd images are still there (check the IMAGE ID), with <none> for REPOSITORY and TAG. But the default is now the Arm64 arch for the httpd image.

[ Learn about Red Hat OpenShift Container Storage for database and analytics. ]

So you can pull an image with a different architecture than the host machine… but what about running a container from it? Check it out:

$ podman run --name=httpd-arm -p 8081:80 -d docker.io/library/httpd
64526b8be8ab570791fb80eaf710e95d60d5c9809ed1a42d9d86d43278367bbf

$ podman ps
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES

$ podman logs httpd-arm
{"msg":"exec container process `/usr/local/bin/httpd-foreground`: Exec format error","level":"error","time":"2022-03-07T21:54:40.000337957Z"}

By default, you aren't allowed to run a container from a different architecture than your host machine. However, there are some tricky ways to do it using emulation and other tweaks. Pulling different architectures like this could still be useful if you're building multi-architecture containers, but that's a topic for another article.

You can still use my old httpd image with the Amd64 arch to run a container in this x86_64 host machine. To demonstrate this, simply do:

$ podman image inspect dabbfbe0c57b | jq -r '.[] | .Architecture'
amd64

$ podman run --name=httpd -p 8081:80 -d dabbfbe0c57b
5a7752378dbee1e32cdd31deab1ea355f925023a38768319dad32a29d635766e

$ podman ps
CONTAINER ID  IMAGE         COMMAND           CREATED        STATUS            PORTS                 NAMES
5a7752378dbe  dabbfbe0c57b  httpd-foreground  6 seconds ago  Up 5 seconds ago  0.0.0.0:8081->80/tcp  httpd

It's clear now how the pulling image process with different arch works in an x86_64 system, so see how it works in an AArch64 system.

Specifying arch when pulling images in an Arm64/AArch64 system

Just to show you that I'm running a real AArch64 system, check the following output:

$ uname -a
Linux fedoraarch 5.16.12-200.fc35.aarch64 #1 SMP Wed Mar 2 18:49:17 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux

Since this is a freshly created machine, it still doesn't have any pulled images:

$ podman image ls
REPOSITORY  TAG         IMAGE ID    CREATED     SIZE

To pull an image here, run the same command and go through the same processes as before:

$ podman pull docker.io/library/httpd
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
Copying blob 0e1e146c1fe7 done  
Copying blob 5ba01719dd76 done  
Copying blob 14e615a0c8e4 done  
Copying blob 279a020076a7 done  
Copying blob d2d2092da38e done  
Copying config c7469bac36 done  
Writing manifest to image destination
Storing signatures
c7469bac360343c88158b2bf384f4521fa0590478c99e077ab4ec2f73b8c5316

$ podman image ls
REPOSITORY               TAG         IMAGE ID      CREATED     SIZE
docker.io/library/httpd  latest      c7469bac3603  5 days ago  141 MB

$ podman inspect docker.io/library/httpd | jq -r '.[] | .Architecture'
arm64

The main difference now is that, as the podman inspect output shows, the pulled image is, by default, an Arm64 architecture. Why is that? It's because podman pull defaults the image architecture to the same arch as the base host machine. Since my base host machine is running an AArch64, Podman pulled an Arm64 arch image. Cool, isn't it?

Running a container from this pulled image should present no issues at all now:

$ podman run --name=httpd-arm -p 8081:80 -d docker.io/library/httpd
391bb0db8da04f6830336088b1d8cbece008e5d85e3fe00bec9d38e95126b082

$ podman ps
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS             PORTS                 NAMES
391bb0db8da0  docker.io/library/httpd:latest  httpd-foreground  20 seconds ago  Up 12 seconds ago  0.0.0.0:8081->80/tcp  httpd-arm

$ curl -s http://localhost:8081
<html><body><h1>Enable SysAdmin - Apache container on aarch64 system </h1></body></html>

It's running! And if you do the opposite now and try to run an Amd64 image on this AArch64 system, will it work? It doesn't hurt to try, right? First, get rid of the running container and pull a fresh httpd image specifying the Amd64 arch:

$ podman stop httpd-arm
httpd-arm

$ podman rm -a
391bb0db8da04f6830336088b1d8cbece008e5d85e3fe00bec9d38e95126b082

$ podman pull --arch=amd64 docker.io/library/httpd
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
Copying blob 4566427976c4 done  
Copying blob f18d7c6e023b done  
Copying blob f7a1c6dad281 done  
Copying blob bf06bcf4b8a8 done  
Copying blob 70a943c2d5bb done  
Copying config faed93b288 done  
Writing manifest to image destination
Storing signatures
faed93b2885914426b66f1a7d09d93dce9e532fa64f4ab269494f4f954a424ef

$ podman image ls
REPOSITORY               TAG         IMAGE ID      CREATED     SIZE
<none>                   <none>      c7469bac3603  5 days ago  141 MB
docker.io/library/httpd  latest      faed93b28859  6 days ago  148 MB

$ podman inspect docker.io/library/httpd | jq -r '.[] | .Architecture'
amd64

And now, as a final test, try to run a container from this image:

$ podman run --name=httpd-amd64 -p 8081:80 -d docker.io/library/httpd
3b1e54611b8aee0bea7937ffe23965213c9696f46471b73d0154e4ce03e49988

$ podman ps
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES

$ podman logs httpd-amd64
{"msg":"exec container process `/usr/local/bin/httpd-foreground`: Exec format error","level":"error","time":"2022-03-07T22:17:47.000637319Z"}

This is the same error that you saw in the other system. This proves the point of running containers of architectures that are compatible with the base system by default.

I hope these demos helped you better understand how to pull images and run containers on systems of different architectures using Podman.

Wrap up

Understanding how the architectures of container images work, how to pull them, and how to run containers from them on different systems is very advantageous for building multi-architecture solutions. It also allows you to explore the many benefits that each architecture may provide.

This is the final article of a five-part series that explored some basic Podman concepts and commands. Topics ranged from creating containers automatically through scripts, extracting information from running containers, getting network and IP information from rootful and rootless containers, and updating image versions. This final article covered pulling different image architectures.

I sincerely hope that this series built an initial foundation for your Podman knowledge. I also hope it sharpened your desire to step into the world of containers and explore its many options. Now that you know how to do it, put it to good use!

Check out these related articles on Enable Sysadmin

Topics:   Podman   Containers  
Author’s photo

Alexon Oliveira

Alexon has been working as a Senior Technical Account Manager at Red Hat since 2018, working in the Customer Success organization focusing on Infrastructure and Management, Integration and Automation, Cloud Computing, and Storage Solutions. More about me

Red Hat Summit 2022: On Demand

Get the latest on Ansible, Red Hat Enterprise Linux, OpenShift, and more from our virtual event on demand.

Related Content

OUR BEST CONTENT, DELIVERED TO YOUR INBOX