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’.
Table of Contents:
What is Podman – A Comprehensive Guide
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
You can also install using the following command:
$ sudo yum install podman -y
$ podman –version
Podman Help
You can view the Podman help documentation using the CLI with the below command:
$ 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
#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
#3) Searching Images
Use the below command to search for images in your registry
podman search [search-item]
$ podman search docker.io/tomcat
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”]
#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
#5) Running Images and Enter the Container– Example 2
$ podman run -d -p 8080:80 –name myhttpd httpd
Enter the container
$ podman exec -it myhttpd /bin/bash
#6) View Container Logs
View the container logs using the command:
podman logs [container-id]
#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]
#8) Remove Images
Remove the images using the below command:
podman rmi [image-name]
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
Inspect the custom bridge created
$ podman network inspect ct-bridge1
Subnet details are shown.
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
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
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 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
Container 1
$ podman run -d -p 8080:80 –name ctr1 -v /home/ec2-user/pvol:/usr/local/apache2/htdocs docker.io/httpd
Enter the container and check the file.
$ podman exec -it ctr1 /bin/bash
Stop and Remove Container 1
$ podman stop ctr1
$ podman rm ctr1
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
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
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
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
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 image
$ podman run -d -p 8080:80 –name vnweb mywebapp:v1
Access the application running in the container by navigating to Public-ip-address:8080 using your web browser.
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
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
You can see that the RUN step executes at image build time and CMD executes every time the container starts.
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.
If now we need to override the command defined (CMD) in the Dockerfile
$ podman run cmdentryexample echo “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.
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 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
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
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
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.
Since the web service is running let’s access it using Public-ip-address:8080 using your web browser.
Shutdown the Services (down command)
The below command will stop and clean the containers specified in the compose file.
$ podman-compose down
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
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
Start the Containers
Start the containers using the ‘podman-compose up -d’ command
$ podman-compose up -d
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
Login to mariadb using the below command
# mariadb -u root -p
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.
$ podman exec -it <New-Container-name-ID> bash
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.
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.