Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

Partner – Orkes – NPI EA (cat=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Introduction

In this tutorial, we’ll look at Podman (short for “Pod Manager”), its features, and usage.

2. Podman

Podman is an open-source container management tool for developing, managing, and running OCI containers. Let’s take a look at some of the advantages of Podman, in comparison with other container management tools:

  • Images created by Podman are compatible with other container management tools – Podman creates images that adhere to the OCI standard; therefore, they can be pushed to other container registries like Docker Hub.
  • It can be run as a normal user without requiring root privileges – Podman creates a user namespace inside which it acquires the root permission when running as a non-root user. This allows it to mount file systems and set up required containers.
  • It provides the ability to manage pods – Unlike the other container runtime tools, Podman lets the user manage pods (a group of one or more containers that operate together). Users can perform operations like creating, listing, and inspecting the pods.
  • It is supported on most OS platforms – Podman also runs on Windows and Mac; whereas Docker containers only run on a Linux-based system or subsystem.
  • It supports running a Compose workload through an external Compose provider – An implementation of the Docker Compose specification available to Podman is podman-compose.

3. Comparison to Docker

Now that we have understood what Podman is and what its advantages and limitations are, let’s compare it with Docker, one of the most widely used container management tools.

3.1. Command Line Interface (CLI)

Podman offers the same set of commands exposed by the Docker client. In other words, there is a one-to-one mapping between the commands of these two utilities.

However, the commands like podman ps and podman images will not show the containers or images created using Docker. This is because Podman’s local repository is /var/lib/containers as opposed to /var/lib/docker maintained by Docker.

3.2. Container Model

Docker uses a client-server architecture for the containers, whereas Podman uses the traditional fork-exec model common across Linux processes. The containers created using Podman, are the child process of the parent Podman process. This is the reason that when the version command is run for both Docker and Podman, Docker lists the versions of both client and server whereas Podman lists only its version.

Sample output for docker version:

Client:
 Version:           24.0.7
 API version:       1.43
 Go version:        go1.22.2
 Git commit:        24.0.7-0ubuntu4.1
 OS/Arch:           linux/amd64
 Context:           default

Server:
 Engine:
  Version:          24.0.7
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.22.2
  Git commit:       24.0.7-0ubuntu4.1
  OS/Arch:          linux/amd64
 containerd:
  Version:          1.7.12

Sample output for podman version:

Client:       Podman Engine
Version:      4.9.3
API Version:  4.9.3
Go Version:   go1.22.2
OS/Arch:      linux/amd64

Since Podman itself runs as a process, it doesn’t require any daemon processes in the background. Unlike Podman, Docker requires a daemon process, Docker daemon, to coordinate the API requests between the client and server.

3.3. Rootless Mode

As mentioned earlier, Podman doesn’t require root access to run its commands. Docker, on the other hand, being dependent on the daemon process, requires root privileges or requires the user to be part of the docker group to be able to run the Docker commands without root privilege.

$ sudo usermod -aG docker $USER

After running this command we can run the docker command without prefixing it with sudo.

4. Installation and Usage

Let’s start by installing Podman. The podman info command displays Podman system information and helps check the installation status.

$ podman info

This command displays the information related to the host such as the Kernel version, swap space used and available and also the information related to Podman such as registries it has access to pull and push images to, storage driver it uses, storage location and others:

host:
  arch: amd64
  buildahVersion: 1.33.7
  cgroupControllers:
  - cpu
  - memory
  - pids
  cgroupManager: systemd
  cgroupVersion: v2
  databaseBackend: sqlite
  eventLogger: journald
  ociRuntime:
    name: crun
    package: crun_1.14.1-1_amd64
    path: /usr/bin/crun
    ...
    rootless: true

Let’s take a look at some of the basic Podman commands.

4.1. Creating an Image

First, we’ll look at creating an image using Podman. Let’s start by creating a Dockerfile with the following content:

FROM ubuntu
RUN apt-get update
RUN apt-get install -y apache2 && apt-get clean
ENTRYPOINT ["/usr/sbin/apache2", "-k", "start"]
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
EXPOSE 80
CMD apachectl -D FOREGROUND

Now let’s create an image called custom-image using the build command:

$ podman build . --tag custom-image

Here we are first pulling the base image of Ubuntu, installing Apache on top of it and then running it as a foreground process with the port 80 exposed. We can access the Apache server by running this image and mapping the exposed port to a host port.

The build command recursively passes all the folders available in the context directory. The current working directory by default becomes the build context when no directory is specified. Hence, it is advisable not to have files and folders that aren’t required for the image creation, in the context directory.

4.2. Listing Available Images

The podman images command lists all the images available. It also supports various options to filter the images.

$ podman images

This command lists all the images available in the local repository. It contains the information on which repository the image was pulled from, the tag, its image id, created time and size.

REPOSITORY                TAG         IMAGE ID      CREATED         SIZE
localhost/custom-image    latest      90eb8d48d651  10 seconds ago  231 MB
docker.io/library/ubuntu  latest      61b2756d6fa9  3 weeks ago     80.6 MB

Accordingly, the base image ubuntu from which we built the custom-image is also listed.

4.3. Running Images

The run command creates a container of a given image and then runs it. Let’s run the custom-image image we have created earlier

$ podman run custom-image

This command first checks if there is a local image available for custom-image. If the image isn’t present locally, it tries to pull the image from the registries that were configured. If the image isn’t present in the registries, it shows an error about being unable to find the image.

The above run command output lists the Usage information for the apachectl command:

Usage: /usr/sbin/apache2 [-D name] [-d directory] [-f file]
                         [-C "directive"] [-c "directive"]
                         [-k start|restart|graceful|graceful-stop|stop]
                         [-v] [-V] [-h] [-l] [-L] [-t] [-T] [-S] [-X]
Options:
  -D name            : define a name for use in  directives
  -d directory       : specify an alternate initial ServerRoot
  -f file            : specify an alternate ServerConfigFile

4.4. Deleting Images

The rmi command removes the images present in the local repository.  We can remove multiple images by providing their ids as space-separated in the input.  Additionally, we specify the -a flag to remove all the images

$ podman rmi 785188cd988c

4.5. Forcibly Deleting Images

When we can’t delete an image with the standard rmi command, we can use additional command options, or alternative commands to forcibly delete an image. Further, we can find what command to use from the command’s help information:

$  podman rmi --help
Remove one or more images from local storage

Description:
  Removes one or more previously pulled or locally created images.

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

Options:
  -a, --all        Remove all images
  -f, --force      Force Removal of the image
  -i, --ignore     Ignore errors if a specified image does not exist
      --no-prune   Do not remove dangling images

Let’s demonstrate removing images forcibly with an example. After running the custom-image, let’s try to remove the image:

$ podman rmi custom-image
Error: image used by 1aaf9c08f: image is in use by a container: consider listing external containers 
and force-removing image

However, we can’t remove the image because it is in use by a container, albeit a stopped container. Therefore, we should forcibly remove the custom-image image, and all dependency images by including the -f, or –force, option:

$ podman rmi --all --force
Untagged: docker.io/library/ubuntu:latest
Untagged: localhost/custom-image:latest
Deleted: 90eb8d48d651f8313efccec72d4e49672e42a398357da5df566d34eb762608c6

Let’s verify the command removed all images:

$ podman images
REPOSITORY  TAG         IMAGE ID    CREATED     SIZE

Indeed, this time it doesn’t list the custom-image image or the other images.

We can remove dangling images as well. Further, we can identify dangling images as unnamed images not associated with any tagged images. Let’s demonstrate with an example how we could get a dangling image, and how to remove it. Let’s create a new image from a container started for the custom-image image:

$ podman commit 846f3cd45420

Afterward, let’s list the images:

$ podman images
REPOSITORY                TAG         IMAGE ID      CREATED             SIZE
<none>                    <none>      ccdabbcd7697  8 seconds ago       231 MB
localhost/custom-image    latest      a918795ac584  About a minute ago  231 MB
docker.io/library/ubuntu  latest      61b2756d6fa9  3 weeks ago         80.6 MB

Thereupon, we can remove the dangling image, which has repository and tag information listed as <none>:

$ podman image prune --force

Yet, we may not be able to remove an image with any of the commands and options discussed. Podman can generate an error message:

Error: unable to delete "a918795ac584" (cannot be forced) -
 image has dependent child images

Even so, we can remove all unused images:

podman system prune --all --force

Furthermore, this command removes all unused containers, pods, and networks.

4.6. Listing the Containers

All the available containers including the ones which aren’t running can be listed using the ps -a command. Similar to the images command, this can also be used with various options.

$ podman ps -a

The output for the above command lists all the containers with the information such as image it was created from, the command used to launch it, its status, ports it’s running on and the name assigned to it.

CONTAINER ID   IMAGE    COMMAND     CREATED AT                      STATUS              PORTS                                    NAMES
eed30719cd37   centos   /bin/bash   2019-12-09 02:57:37 +0000 UTC   Up 14 minutes ago   0.0.0.0:80->80/udp, 0.0.0.0:80->80/tcp   reverent_liskov

4.7. Deleting Containers

The rm command removes the containers. This command does not remove the containers in running or paused state. They need to be first stopped and then removed.

$ podman stop eed30719cd37

$ podman rm eed30719cd37

4.8. Creating Pods

The pod create command creates a pod.  The create command supports different options.

$ podman pod create

The pod create command creates a pod with an infra container by default associated with it unless explicitly set with infra flag as false.

$ podman pod create --infra=false

Infra container allows Podman to connect various containers in the pod.

4.9. Listing Pods

The pod list command displays all the available pods

$ podman pod list

The output of this command displays the information such as the pod id, its name, number of associated containers, the id of the infra container if available:

POD ID         NAME             STATUS      CREATED       # OF CONTAINERS   INFRA ID
7e0a68528aed   gallant_raman    Running    5 seconds ago        1           c6d06673c667

All the available Podman commands and their usage can be found in the official documentation.

5. Conclusion

In this tutorial, we’ve looked at the basics of Podman and its features, its comparison to Docker and a few of the commands available.

As usual, the code sample used in this article is available over GitHub.

2 Comments
Oldest
Newest
Inline Feedbacks
View all comments