What is Podman? Explore This Docker Alternative

By Sruthy

By Sruthy

Sruthy, with her 10+ years of experience, is a dynamic professional who seamlessly blends her creative soul with technical prowess. With a Technical Degree in Graphics Design and Communications and a Bachelor’s Degree in Electronics and Communication, she brings a unique combination of artistic flair…

Learn about our editorial policies.
Updated April 2, 2024

A detailed guide on what is Podman. Explore all about Podman which is a free and open-source option for managing containers, images & pods, thereby serving as an alternative to Docker:

Podman (Pod Manager) is a daemonless, free, and open-source Linux-based native tool that builds, runs, and deploys applications using Open Containers Initiative (OCI) Containers and Container Images. With the recent updates to the docker license, it has emerged as a practical substitute, especially for large enterprises.

So, teams using the docker engine for a long time will not face any difficulty in using Podman as most of the functionality is similar. It has support for a Docker-compatible type of CLI interface. For example, the ‘docker pull’ command will become ‘Podman pull’.

What is Podman – A Comprehensive Guide

Podman Docker Featured image

Podman has support for running containers without root or elevated privileges, which means it can run as a normal user. This is known as rootless. Podman supports running containers on Linux, Windows (using WSL2) and MacOS.

Recommended Reading => Docker Tutorial: Introduction To Docker

Install Podman on RHEL 9

Podman can be installed from a group of container tools. The below command will install all the tools for building, running, and managing containers including the ‘podman-docker’ package which replaces the Docker command-line interface.

$ sudo yum install container-tools

Install Podman on RHEL 9

You can also install using the following command:

$ sudo yum install podman -y

$ podman –version

Install Podman on RHEL 9

Podman Help

You can view the Podman help documentation using the CLI with the below command:

$ podman help

Podman Help

Basic Podman Commands for Images

In this section, let’s look at some basic and important commands of Podman for images

#1) Login to DockerHub

$ podman login

Login to DockerHub

#2) Downloading Images

Pull images from registries that are online using the format below:

podman pull [registry/image]

$ podman pull docker.io/tomcat

List locally available images

$ podman images

Downloading images

#3) Searching Images

Use the below command to search for images in your registry

podman search [search-item]

$ podman search docker.io/tomcat

Searching images

If you want to configure Podman to search only in the docker.io registry, you can change the following option to point to only “docker.io” in the file /etc/containers/registries.conf directory.

unqualified-search-registries = [“docker.io”]

Searching images

#4) Running Images – Example 1

Run the podman images in the background using the below command:

podman run -d [imagename]

$ podman run -d -p 8080:8080 docker.io/tomcat

Running images – Example 1

#5) Running Images and Enter the Container– Example 2

$ podman run -d -p 8080:80 –name myhttpd httpd

Running images and enter the container– Example 2

Enter the container

$ podman exec -it myhttpd /bin/bash

Enter the container

#6) View Container Logs

View the container logs using the command:

podman logs [container-id]

View container logs

#7) Stop and Remove Containers

Stop and remove containers using the below commands.

$ podman stop [container-id]

Once the container is stopped, you can start using the ‘podman start [container-id]’ command

$ podman rm [container-id]

Stop and remove containers

#8) Remove Images

Remove the images using the below command:

podman rmi [image-name]

Remove images

Podman Network

Podman also supports container networking to enable communication between containers and also build complex application deployments. The default podman network is a Bridge network. This network automatically created an IP subnet and gateway.

Containers belonging to this network are a part of the same subnet. So, containers in this network communicate via IP address.

Let’s create a custom bridge network and check for connectivity between 2 containers of the same bridge.

$ podman network create –driver bridge ct-bridge1

create a custom bridge network

Inspect the custom bridge created

$ podman network inspect ct-bridge1

Subnet details are shown.

Inspect the custom bridge created

Now let’s attach 2 containers to this bridge and establish connectivity. Once 2 containers are created you can run the command ‘podman inspect container-name’ and view the IP address of the containers which is part of the same subnet as shown above of the custom bridge.

  • Attach Container 1 to the custom bridge

$ podman run -it –network ct-bridge1 –name ctr1 –privileged busybox

–privileged option is used for running rootless podman as a non-root user. A “privileged” container is given the same access as the user launching the container

Attach Container 1 to the custom bridge

To keep container 1 running and to come out without exiting press CTRL+P+Q

  • Attach Container 2 to the custom bridge

$ podman run -it –network ct-bridge1 –name ctr2 –privileged busybox

Attach Container 2 to the custom bridge

To keep container 2 running and to come out without exiting press CTRL+P+Q

Attach to running container. Use the ‘podman attach’ command to attach your terminal’s standard input, output, and error to a running container using the container’s ID or name. Let’s attach to ctr1 and communicate to ctr2 using the ping command since both are part of the same bridge network.

$ podman attach ctr1

podman attach ctr1

Podman Volumes

Data created inside the container is only available within the container while it is running. When the container no longer exists, the data is difficult to get if another container needs it. So, volumes are key from a data persistence point of view, which are filesystems mounted on the containers to preserve data.

There are 2 options for the container to store files in the host system where the files are persisted even after the container stops.

  • Volume Mount: These are stored as part of the host filesystem
  • Bind Mount: These can be stored anywhere in the host system

Volumes allow users to back up data and share file systems between containers easily.

Bind Mount Example

Bind mount will mount a directory from your host machine onto the container which can be referenced through the absolute path. We will create 2 containers from an image. Look at the directory from the host machine to be available in container 1 then stop/remove container 1 and ensure that the same directory is available in container 2 as well.

Let’s create a file called index.html in the directory /home/ec2-user/pvol

$ echo ‘Hello from Podman Host’ > index.html

Bind Mount Example

Container 1

$ podman run -d -p 8080:80 –name ctr1 -v /home/ec2-user/pvol:/usr/local/apache2/htdocs docker.io/httpd

Container 1

Enter the container and check the file.

$ podman exec -it ctr1 /bin/bash

Stop and remove container 1

Stop and Remove Container 1

$ podman stop ctr1

$ podman rm ctr1

Stop and Remove Container 1

Container 2

Make the directory on the host filesystem available in Container 2

$ podman run -d -p 8080:80 –name ctr2 -v /home/ec2-user/pvol:/usr/local/apache2/htdocs docker.io/httpd

$ podman exec -it ctr2 /bin/bash

Container 2

Stop and Remove container 2 as shown above for Container 1.

Volume Mount Example (Named Volume)

The podman volume creates command will create an empty volume and will be used by containers.

$ podman volume create ctr-vol1

Volume Mount Example (Named Volume)

Note: The Mountpoint path in the output above which is managed by Podman. Create files in the path which will be mounted to a directory within the container.

$ touch /home/ec2-user/.local/share/containers/storage/volumes/ctr-vol1/_data/file1.txt

Volume Mount Example (Named Volume)

To mount this volume ctr-vol1 on the host machine to the /var/www/html directory in the container, run the following command. In the command below, use the -v flag followed by the name of the volume and the path of the directory inside the container. If the named volume does not exist, Podman will create one

$ podman run -d -p 8080:80 –name ctr1 -v ctr-vol1:/var/www/html httpd

$ podman exec -it ctr1 bash

Volume Mount Example (Named Volume)

So, Volumes are stored on the host which is independent of the lifecycle of the container.

Podman image build using Dockerfile

A Dockerfile is a text file that contains instructions or a set of commands to build an image. We will use the ‘podman build’ command to build an image.

Common Tags used in Dockerfile:

  • FROM: Specifies the base image for the image to be built
  • RUN: Execute a command at image build time
  • CMD: Specifies a command to be run when the container is started
  • ENV: Sets the environment variable in the container
  • COPY: Copy files or directories from the host machine to the container
  • ADD: It is similar to COPY but also allows files to be copied from a URL and also copy a tarball from the local system and extract it inside the container
  • WORKDIR: Set the working directory inside the container
  • EXPOSE: Expose specific port for use by the container
  • USER: User to use when running the container

Podman image build using Dockerfile can be done by running the command ‘podman build’ which takes 2 arguments -t and imagename:tag. If no tag is specified, then the latest tag will be added to the image.

Example #1: Sample index.html file and using the httpd image

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Welcome to Podman</title>
</head>
<body>
    <h1>Podman Host</h1>
    <p>The program is built using Podman</p>
</body>
</html>

Let’s look at the below sample Dockerfile which will build using Podman.

FROM docker.io/httpd:2.4
MAINTAINER V Niranjan
COPY index.html /usr/local/apache2/htdocs
EXPOSE 80

Run the Podman build from the directory where the Dockerfile is stored.

$ podman build -t mywebapp:v1 .

Run the Podman build from the directory where Dockerfile is stored

Run the image

$ podman run -d -p 8080:80 –name vnweb mywebapp:v1

Run the image

Access the application running in the container by navigating to Public-ip-address:8080 using your web browser.

Podman Host

The ADD instruction can also fetch remote URLs, and extract TAR/ZIP files in the destination.

Example of ADD instruction

ADD https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.17/bin/apache-tomcat-10.1.17.tar.gz /opt/tomcat10

Example #2: Running a Java program

Let’s look at the Dockerfile.

FROM docker.io/openjdk:17
MAINTAINER V Niranjan
RUN mkdir /app
COPY HelloWorld.java /app
WORKDIR /app
RUN javac HelloWorld.java
ENTRYPOINT [“java”, “HelloWorld”]

Podman Build and Run.

$ podman build -t myjava:v1 .

$ podman run myjava:v1

Podman Build and Run

Example #3: RUN and CMD instructions example

Let’s look at the Dockerfile.

FROM docker.io/centos:7
MAINTAINER V Niranjan
RUN date
CMD date

Podman Build and Run

$ podman build -t mydate:v1 .

$ podman run mydate:v1

Podman Build and Run

You can see that the RUN step executes at image build time and CMD executes every time the container starts.

Tip

RUN as we are aware now is an image-build step. For example, if you want to install a package create a directory inside of your Docker image, or compile a Java program, then RUN will be what you’ll want to use. You can have multiple RUN commands in the Dockerfile.

CMD as we know now it specifies what command to run within the container at startup. For example, start your web application app server or run a Java program. There should be a single CMD command within a Dockerfile. If there are multiple CMD commands, then all except the LAST one is ignored for execution

Example #4: CMD and ENTRYPOINT example

CMD and ENTRYPOINT instructions have fundamental differences in how they function. They both specify programs that execute when the container runs.

The CMD command is used to specify the default parameters or commands for a container. We can override the default command.

With ENTRYPOINT if an image needs to be dedicated to a specific command, then use this instruction.

Let’s look at these differences with an example.

#1) Dockerfile with CMD

FROM ubuntu
MAINTAINER V Niranjan
CMD echo ‘Welcome to Podman’

Podman Build and Run

$ podman build -t cmdentryexample .

$ podman run cmdentryexample

It prints the message as in the Dockerfile when the container starts.

prints the message as in Dockerfile

If now we need to override the command defined (CMD) in the Dockerfile

$ podman run cmdentryexample echo “Welcome to the world of Podman”

Welcome to the world of Podman

#2) Dockerfile with ENTRYPOINT

FROM ubuntu
MAINTAINER V Niranjan
ENTRYPOINT echo ‘Welcome to Podman’

Podman Build and Run

$ podman build -t cmdentryexample.

$ podman run cmdentryexample

It prints the message as in the Dockerfile when the container starts.

prints the message as in Dockerfile

Let’s try to override the command defined (ENTRYPOINT) in the Dockerfile, which is not possible

$ podman run cmdentryexample echo “Welcome to the world of Podman”

podman run cmdentryexample

Podman Compose

Podman has a compose tool that allows you to work with Docker compose files. So, the tool name is podman-compose which is an alternative to docker-compose. Podman-compose adheres to the compose specification and hence it is compatible with the docker-compose.yml file. To install podman-compose on RHEL9 using pip3, follow the below steps:

$ sudo pip3 install podman-compose

Podman Compose

When running the pip3 install command as sudo, you may see some warning messages. You can safely ignore the same.

Verify the installation

To verify that podman-compose is installed and set properly in the PATH environment variable run the following command

$ podman-compose –version

Verify the installation2

Docker Compose, as you are aware, is a tool for defining multi-container applications. With Compose, users can define the services in a YAML file. And the developers use it to orchestrate containers.

Creating the docker-compose file and use podman-compose

Example docker-compose.yml file. The services section in the file specifies multiple containers which will be created.

version: ‘3.8’
services:
web:
image: httpd
ports:
– 8080:80
database:
image: redis

Check the validity of the composed file

$ podman-compose config

Check validity of the compose file

Start the Services (up Command)

We will need to use the below command to start or restart all the services as defined in the docker-compose.yml file. The command will help to create the containers specified in the docker-compose.yml file. To run the command, you should be in the directory where the docker-compose.yml file is present.

$ podman-compose up -d

The -d option will run the containers in the background. ‘podman ps’ command will show the newly created containers.

Start the services (up Command)

Since the web service is running let’s access it using Public-ip-address:8080 using your web browser.

It Works

Shutdown the Services (down command)

The below command will stop and clean the containers specified in the compose file.

$ podman-compose down

Shutdown the services (down command)

podman-compose up and down will start and stop ALL services. If only one service needs to stop/start then we can use the stop/start command for individual services.

$ podman-compose stop <ServiceName>

$ podman-compose start <ServiceName>

$ podman-compose restart <ServiceName>

Podman Compose Build

In this section, we will look at an example of Podman Compose Build. The Podman Compose provides a subcommand to build the images which is ‘podman-compose build’. The command will go through all the services and build the images which are in the ‘build’ section.

Example #1

Create a Dockerfile in a webapp directory and add the content as shown.

$ vi webapp/Dockerfile

FROM httpd
COPY index.html /var/www/html

Podman Compose Build

docker-compose.yml file

version: “3.8”
services:
web:
build: ./webapp
ports:
– “8080:80”

redis:
image: redis

Note: The build section above refers to the location of the Dockerfile.

Build the web service from the compose file

Build the image using the ‘docker-compose build’ command. For the web service, it will use the webapp/Dockerfile

$ podman-compose build

Build the web service from the compose file

Start the Containers

Start the containers using the ‘podman-compose up -d’ command

$ podman-compose up -d

Start the containers

Podman Compose and Volumes

As we are aware data is stored inside the container. Once the container is removed, data will also be lost. So, volumes in docker help to preserve the data even if containers are removed. Users can also share the volumes across different containers.

If you want to save your data locally on your host machine or want to share data from your host to the container e.g., conf files or any other source code, then this type of volume is called a Bind mount.

If you want Podman to manage the data and the mount points, then this type of volume is called Volume mount.

In this section, as an example, we will use the mysql image with bind mount where the DB data will be persisted even if the container is removed.

docker-compose.yml file

version: ‘3’
services:
db:
image: mariadb:latest
environment:
MARIADB_USER: niranjan
MARIADB_PASSWORD: alpha123
MARIADB_DATABASE: testdb
MARIADB_ROOT_PASSWORD: root
volumes:
– db_vol:/var/lib/mysql

volumes:
db_vol:

Start the Containers

Start the containers using the ‘podman-compose up -d’ command

$ podman-compose up -d

$ podman exec -it <Container-Name> bash

Podman Compose and Volumes

Login to mariadb using the below command

# mariadb -u root -p

Login to mariadb using the below command

Create a database inside the container

Create a database inside the container

Shutdown the Service

Exit the container and shut the services

$ podman-compose down

The container is removed but the data is persisted. Let’s now start the services again and check in the NEW container created.

Shutdown the service

$ podman exec -it <New-Container-name-ID> bash

New-Container-name-ID

The database created earlier ‘vndb’ is listed in this new container as well.

Docker V/S Podman

In this section, we will look at some similarities and differences between Docker and Podman.

Docker vs Podman

Further Reading => What is Docker Compose – Explore the Installation Process

Summary

In this article, we have seen Podman as an alternative to Docker, which is a free and open-source tool to manage containers, images, and pods. Most importantly, Podman is easy to install and use as it is daemonless, secure, and fast.

Podman is also compatible with other OCI compliant container tools like Docker which we have seen in this article using various examples.

Thank you and Happy Reading.

Was this helpful?

Thanks for your feedback!

Leave a Comment