The Ultimate Guide to Podman, Skopeo and Buildah

The docker daemon and docker command represent a bundled container runtime environment for managing containers. With the advent of standards from the Open Container Initiative (OCI), other runtimes are being developed. One such runtime is CRI-O, which was created along with a set of tools to provide alternate ways to work directly with containers.

The following text describes some of the tools being developed to use with the CRI-O runtime or as alternative container stand-alone tools. These tools can be used with docker-formatted containers or OCI-conformant containers. While some of these commands were made to use with CRI-O, others can also interact with the docker daemon (as a replacement for features of the docker command) or used to manage containers with no active runtime environment.

  • podman: The podman command can run and manage containers and container images. It supports most of the same features and command options you find in the docker command, with the main differences being that podman doesn’t require the docker service or any other active container runtime for the command to work. Also, podman stores its data in the same directory structure used by CRI-O, which will allow podman to eventually work with containers being actively managed by CRI-O in OpenShift.
  • skopeo: The skopeo command lets you inspect images from container image registries, get images and image layers, and use signatures to create and verify images.
  • Buildah: The buildah command can be used in place of docker build to build container images from Dockerfiles and, ultimately, files in other formats.

The following sections describe podman, runc, skopeo, and buildah.

 Using podman to work with containers

 The podman command lets you run containers as standalone entities, without requiring that Kubernetes, the Docker runtime, or any other container runtime be involved. It is a tool that can act as a replacement for the docker command, implementing the same command-line syntax, while it adds even more container management features. The podman features include:

  • Based on docker interface: Because podman syntax mirrors the docker command, transitioning to podman should be easy for those familiar with docker.
  • Managing containers and images: Both Docker- and OCI-compatible container images can be used with podman to:
    • Run, stop and restart containers
    • Create and manage container images (push, commit, configure, build, and so on)
  • Working with no runtime: No runtime environment is used by podman to work with containers.

Podman uses the CRI-O back-end store directory, /var/lib/containers, instead of using the Docker storage location (/var/lib/docker), by default.

Installing podman

 To start using podman to work with containers, you can simply install it on a Red Hat Enterprise Linux server system or try it on a RHEL Atomic Host (podman is preinstalled on RHEL Atomic Host 7.5.1 or later). No container runtime is needed to use podman.

To install podman on a RHEL server system, do the following:
# yum install podman -y

 

Running containers with podman

If you are used to using the docker command to work with containers, you will find most of the features and options match those of podman. Table 1 shows a list of commands you can use with podman (type podman -h to see this list):

Trying basic podman commands

Because the use of podman mirrors the features and syntax of the docker command, you can refer to Working with Docker Formatted Container Images for examples of how to use those options to work with containers. Simply replace docker with podman in most cases. Here are some examples of using podman.

Pull a container image to the local system
# podman pull fedora

List local container images
# podman images

Run a container image: This runs a container image and opens a shell inside the container:
# podman run -it rhel /bin/bash

List containers that are running or have exited
# podman ps -a

Remove a container or image: remove a container by its container ID:
# podman rm 440becd26893

Remove a container image by its image ID or name (use -f to force):
# podman rmi registry.access.redhat.com/rhel7/rhel-minimal
# podman rmi de9c26f23799
# podman rmi -f registry.access.redhat.com/rhel7/rhel:latest

Build a container
# cat Dockerfile

FROM docker.io/ubuntu

ENTRYPOINT “echo “Podman build this container.”

# podman build -t podbuilt .
# podman run podbuilt

 

Using skopeo to work with container registries

With the skopeo command, you can work with container images from registries without using the docker daemon or the docker command. Registries can include the Docker Registry, your own local registries, or Atomic registries. Activities you can do with skopeo include:

  • inspect: The output of a skopeo inspect command is similar to what you see from a docker inspect command: low-level information about the container image. That output can be in json format (default) or raw format (using the –raw option).
  • copy: With skopeo copy you can copy a container image from a registry to another registry or to a local directory.
  • layers: The skopeo layers command lets you download the layers associated with images so that they are stored as tarballs and associated manifest files in a local directory.

Like the buildah command and other tools that rely on the containers/image library, the skopeo command can work with images from container storage areas other than those associated with Docker. Available transports to other types of container storage include: containers-storage (for images stored by buildah and CRI-O), ostree (for atomic and system containers), oci (for content stored in an OCI-compliant directory), and others. See the skopeo man page for details.

Inspecting container images with skopeo

 When you inspect a container image from a registry, you need to identify the container format (such as docker), the location of the registry (such as docker.io or localhost:5000), and the repository/image (such as rhel).

To install skopeo
# yum install skopeo

The following example inspects the mariadb container image from the Docker Registry:
# skopeo inspect docker://docker.io/library/mariadb

Copying container images with skopeo: this command copies the myrhel7 container image from a local registry into a directory on the local system:
# skopeo copy docker://localhost:5000/myrhel7 dir:/root/test/

The result of the skopeo copy command is a tarball (16d*.tar) and a manifest.json file representing the image begin copied to the directory you identified. If there were multiple layers, there would be multiple tarballs. The skopeo copy command can also copy images to another registry. If you need to provide a signature to write to the destination registry, you can do that by adding a –sign-by= option to the command line, followed by the required key-id.

Getting image layers with skopeo: The skopeo layers command is similar to skopeo copy, with the difference being that the copy option can copy an image to another registry or to a local directory, while the layers option just drops the layers (tarballs and manifest.jason file) in the current directory. For example
# skopeo layers docker://localhost:5000/myrhel7

 

Building container images with Buildah

 The buildah command lets you create container images from a working container, a Dockerfile, or from scratch. The resulting images are OCI compliant, so they will work on any runtimes that meet the OCI Runtime Specification (such as Docker and CRI-O).

Understanding Buildah

 Using Buildah is different from building images with the docker command in the following ways:

  • No Daemon!: Buildah bypasses the Docker daemon! So no container runtime (Docker, CRI-O, or other) is needed to use Buildah.
  • Base image or scratch: Lets you not only build an image based on another container, but also lets you start with an empty image (scratch).
  • Build tools external: Doesn’t include build tools within the image itself. As a result, Buildah:
    • Reduces the size of images you build
    • Makes the image more secure by not having the software used to build the container (like gcc, make, and dnf) within the resulting image.
    • Creates images that require fewer resources to transport the images (because they are smaller).

Buildah is able to operate without Docker or other container runtimes by storing data separately and by including features that let you not only build images, but run those images as containers as well. By default, Buildah stores images in an area identified as containers-storage (/var/lib/containers). When you go to commit a container to an image, you can export that container as a local Docker image by indicating docker-daemon (stored in /var/lib/docker).

There are more than a dozen options to use with the buildah command. Some of the main activities you can do with the buildah command include:

  • Build a container from a Dockerfile: Use a Dockerfile to build a new container image (buildah bud).
  • Build a container from another image or scratch: Build a new container, starting with an existing base image (buildah from <imagename>) or from scratch (buildah from scratch)
  • Inspecting a container or image: View metadata associated with the container or image (buildah inspect)
  • Mount a container: Mount a container’s root filesystem to add or change content (buildah mount).
  • Create a new container layer: Use the updated contents of a container’s root filesystem as a filesystem layer to commit content to a new image (buildah commit).
  • Unmount a container: Unmount a mounted container (buildah umount).
  • Delete a container or an image: Remove a container (buildah rm) or a container image (buildah rmi).

Installing Buildah

 To install Buildah:
# yum -y install buildah

Getting Images with buildah: To get a container image to use with buildah, use the buildah from command. Here’s how to get a RHEL 7 image from the Red Hat Registry as a working container to use with the buildah command:
# buildah from docker://docker.io/fedora

Notice that the result of the buildah from command is an image, and a working container that is ready to run from that image (fedora-working-container).

To list the containers by Buildah
# buildah containers

Here’s an example of how to execute a command from that container:
# buildah run fedora-working-container cat /etc/redhat-release

Inspecting a Container with buildah: With buildah inspect, you can show information about a container or image. For example, to inspect the myecho image you created earlier, type:
# buildah inspect myecho | less

 

Podman Vs. Buildah

Buildah and Podman are two complementary Open-source projects that are available on most Linux platforms. Both Buildah and Podman are command line tools that work on OCI images and containers. The two projects are related, but differ in their specialization.

Podman allows you to do all of the Docker commands without the daemon dependency. With Podman you can run, build (it calls Buildah under the covers for this), modify and troubleshoot containers in your Kubernetes cluster. With the two projects together, you have a well rounded solution for your OCI container image and container needs.

Podman specializes in all of the commands and functions that help you to maintain and modify those OCI container images, such as pulling and tagging. It also allows you to create, run, and maintain those containers. If you can do a command in the Docker CLI, you can do the same command in the Podman CLI. In fact you can just alias ‘podman’ for ‘docker’ on your machine and you can then build, create and maintain container images and containers without a daemon being present, just as you always have.

Buildah specializes in building OCI images. Buildah’s commands replicate all of the commands that are found in a Dockerfile. Buildah’s goal is also to provide a lower level coreutils interface to build container images, allowing people to build containers without requiring a Dockerfile. Buildah’s other goal is to allow you to use other scripting languages to build container images without requiring a daemon.

Each project has a separate internal representation of a container that is not shared. Because of this you cannot see Podman containers from within Buildah or vice versa. However the internal representation of a container image is the same between Buildah and Podman. Given this, any container image that has been created, pulled or modified by one can be seen and used by the other

Some of the commands between the two projects overlap significantly but in some cases have slightly different behaviors. The following table illustrates the commands with some overlap between the projects.

Command Podman Behavior Buildah Behavior
build Calls buildah bud Provides the build-using-dockerfile (bud) command that emulates Docker’s build command.
commit Commits a Podman container into a container image. Does not work on a Buildah container. Once committed the resulting image can be used by either Podman or Buildah. Commits a Buildah container into a container image. Does not work on a Podman container. Once committed, the resulting image can be used by either Buildah or Podman.
mount Mounts a Podman container. Does not work on a Buildah container. Mounts a Buildah container. Does not work on a Podman container.
pull and push Pull or push an image from a container image registry. Functionally the same as Buildah. Pull or push an image from a container image registry. Functionally the same as Podman.
run Run a process in a new container in the same manner as docker run. Runs the container in the same way as the RUN command in a Dockerfile.
rm Removes a Podman container. Does not work on a Buildah container. Removes a Buildah container. Does not work on a Podman container.
rmiimagestag Equivalent on both projects. Equivalent on both projects.
containers and ps ps is used to list Podman containers. The containers command does not exist. containers is used to list Buildah containers. The ps command does not exist.

Sources:
[1] Finding, Running And Building Containers Without Docker: https://red.ht/2x9MpNq
[2] Containers Without Docker: https://red.ht/2FmnGKG