Building Multi-Architecture Containers on OCI with Podman
Many of us have started using Podman. Whether it’s the desire to leverage open-source tooling as much as possible or preferring an easier install (such as sudo dnf install podman on Oracle Linux 8) than some other alternatives, Podman is a viable solution for many developers when it comes to building and running containers. This is a continuation of the topic, where we’ve already discussed high-level implications of working with containers in a multi-architectural world and how to build multi-architecture containers with Docker. This article will deal with the practicalities of building multi-architectural containers using Podman.
Prerequisites
I assume that you have an OCI account and have created an OCI Container Repository (OCIR) called hello-world. If you want to follow along and try this for yourself, make sure that you have this repository. See the OCI docs for more info on how to create a repository.
For this scenario, I’ve used a Podman v3.4.2 on Oracle Linux 8 (more specifically, 8.5). Different versions might result in different results.
One of the first things you’ll need to do is to get Podman logged in to OCIR:
$ podman login phx.ocir.io
Make sure to update the above hostname to whatever region you’re using! See the region availability for region-specific URLs. The OCI Container Registry documentation talks about this in greater detail and you can also find the region keys in the OCI documentation.
The username to use is <namespace>/<username> (or if you’re using IDCS, <namespace>/oracleidentitycloudservice/<username>). The password will be an Auth Token associated with your account. If this seems a bit foreign or confusing, take a look at the OCI documentation for more details.
Once you’re all done with this exercise, you can logout of OCIR with:
$ podman logout phx.ocir.io
Building the Containers
We’ll work with a super basic Dockerfile:
FROM container-registry.oracle.com/os/oraclelinux:8-slim
CMD echo “Hello world!”
Nothing special here, it’s just a simple example. In an effort to keep this focused on the container building (not language-specific complexities), I’ve totally omitted any specific application binary.
To do our due diligence, let’s confirm that the base image is available in both architectures that we’ll be building for. Looking at the Oracle Container Registry (to follow along yourself, click on OS then oraclelinux) for this container, we can see that there are two platforms supported (both of which we’re wanting to build against):
It’s always a good idea to check this, as your base image should exist in the different target architectures you’ll be building against.
Now we need to create the two container images (one for each architecture: arm64 and amd64):
$ podman build --platform linux/arm64/v8 -t phx.ocir.io/<namespace>/hello-world:v1.0.0-linux-arm64 .
<omitted for brevity>$ podman build --platform linux/amd64 -t phx.ocir.io/<namespace>/hello-world:v1.0.0-linux-amd64 .
<omitted for brevity>
The — platform argument is used to specify the desired target architecture (the architecture that the container will be built for). For a bit of context, a platform typically consists of an operating system, architecture, and a variant (which is optional and often times excluded), with each being separated by a forward-slash (/).
To confirm that things are looking good, take a look at the container images that were built:
$ podman image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
phx.ocir.io/<namespace>/hello-world v1.0.0-linux-amd64 de9a0c2f01c8 29 seconds ago 114 MB
phx.ocir.io/<namespace>/hello-world v1.0.0-linux-arm64 0f3a0bc46798 43 seconds ago 136 MB
container-registry.oracle.com/os/oraclelinux 8-slim b7c162609f52 6 days ago 114 MB$ podman image inspect phx.ocir.io/<namespace>/hello-world:v1.0.0-linux-amd64 | grep Arch
"Architecture": "amd64",$ podman image inspect phx.ocir.io/<namespace>/hello-world:v1.0.0-linux-arm64 | grep Arch
"Architecture": "arm64",
The above output is a bit garbled, but if you squint long enough and hard enough, you’ll see that there are two hello-worldcontainers. Both were inspected and confirmed to be for the proper architecture (yay!), so we’re ready to proceed with pushing the images to the OCI Registry (OCIR).
$ podman push phx.ocir.io/<namespace>/hello-world:v1.0.0-linux-amd64
<omitted for brevity>$ podman push phx.ocir.io/<namespace>/hello-world:v1.0.0-linux-arm64
<omitted for brevity>
We now have two images in OCIR. For this to be easy-to-consume (run), we need to create a manifest.
Creating the Manifest
Here’s how to make the manifest using Podman:
$ podman manifest create \
phx.ocir.io/<namespace>/hello-world:v1.0.0 \
phx.ocir.io/<namespace>hello-world:v1.0.0-linux-arm64 \
phx.ocir.io/<namespace>hello-world:v1.0.0-linux-amd64$ podman manifest push phx.ocir.io/<namespace>/hello-world:v1.0.0 docker://phx.ocir.io/<namespace>/hello-world:v1.0.0$ docker manifest rm phx.ocir.io/<namespace>/hello-world:v1.0.0
The first command creates the manifest (hello-world:v1.0.0) and then adds two containers to it (hello-world:v1.0.0-linux-amd64 and hello-world:v1.0.0-arm64).
The second command pushes the manifest to OCIR.
For grins, let’s inspect the manifest:
$ podman manifest inspect phx.ocir.io/<namespace>/hello-world:v1.0.0
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 569,
"digest": "sha256:de9a0c2f01c8...",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 569,
"digest": "sha256:0f3a0bc46798...",
"platform": {
"architecture": "arm64",
"os": "linux"
}
}
]
}
And once we’ve pushed it to OCIR, we really don’t need to keep it around in the local cache, so we can remove it:
$ podman manifest rm phx.ocir.io/<namespace>/hello-world:v1.0.0
Conclusion
Podman is a great tool. It supports what we need to effectively build multi-architecture container images (and manifests), making it a valuable tool in our toolbelt!
There’s still more to come in this series, where we’ll explore how to do the same thing using Buildah. Stay tuned…
Questions? Swing by our public Slack to discuss!
Remember, you can always try this out for free using our Free Tier.