
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.
Last updated: November 6, 2023
In this tutorial, we’ll look at Podman (short for “Pod Manager”), its features, and usage.
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:
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.
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.
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.
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.
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.
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.
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.
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
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
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.
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
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
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.
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.
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.