With the latest release of Red Hat Enterprise Linux, and one of its continuing features is Podman. Podman offers an experience similar to the Docker command line, allowing users to run standalone (non-orchestrated) containers without requiring a daemon, enabling us to say goodbye to big fat daemons. Podman also complements similar container tools such as Buildah and Skopeo, offering a comprehensive and flexible toolkit for your container needs.
Podman implements nearly all the Docker CLI commands. Additionally, Podman's design, which does not require any background daemons, makes it a suitable choice for integration into system services via systemd
. For container orchestration, you might want to explore Kubernetes and Red Hat OpenShift.
We'll cover some real examples to show how easy transitioning from the Docker CLI to Podman can be. (See also: Transitioning from Docker to Podman)
Podman installation
If you are running Red Hat Enterprise Linux 9.2 or Red Hat Enterprise Linux 8, follow the step below. This command will also work for CentOS, where Podman is available in the default repo for CentOS 7 and 8. If not, you can try our interactive lab on how to deploy a container using Podman.
To install the podman package, simply execute the command:
# yum install -y podman
This command will install Podman and also its dependencies. Now you can start experimenting with Podman!
Command-line examples
Run a UBI (Universal Base Image) Container
Let's start by running a UBI (Universal Base Image) container. Assuming you are on a RHEL system, execute the below command. After you see the shell prompt, you are inside the running UBI container.
# podman run -it registry.access.redhat.com/ubi9/ubi sh Trying to pull registry.access.redhat.com/ubi9/ubi:latest... Getting image source signatures Checking if image destination supports signatures Copying blob 33b9f09cff46 done Copying config e7236a3e07 done Writing manifest to image destination Storing signatures sh-5.1#
Now you have a RHEL container running. You can use the ls
command to list non-hidden files in the current directory and exit
to leave the container's shell.
sh-5.1# ls afs boot etc lib lost+found mnt proc run srv tmp var bin dev home lib64 media opt root sbin sys usr sh-5.1# exit exit
You can now explore various Podman commands to check the status of your containers and delete containers or images as needed.
To view the status of your containers, execute:
# podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1d49374d4964 registry.access.redhat.com/ubi9/ubi:latest sh 10 minutes ago Exited (0) 2 minutes ago loving_mendeleev second ago reverent_torvalds
To remove a container, use the podman rm
command followed by the container ID:
# podman rm 1d49374d4964 1d49374d4964
To remove an image, use the podman image rm
command followed by the image name:
# podman image rm registry.access.redhat.com/ubi9/ubi:latest Untagged: registry.access.redhat.com/ubi9/ubi:latest Deleted: e7236a3e070f267713ad79c451b8628166abc0bc9c855f624619e099ec3faa99
As you can see, we used the same syntax as we'd use with docker
.
Run a MariaDB persistent container
Let's move on to a more complicated example: running a MariaDB 10.5 SQL database server container with custom variables and persistent data.
First, download the MariaDB container image and inspect its details:
# podman pull docker.io/library/mariadb:10.5 Trying to pull docker.io/library/mariadb:10.5... Getting image source signatures Copying blob 818ec8e8ed03 done ... Copying config 9a79847e85 done Writing manifest to image destination Storing signatures 9a79847e85fb307d90864c991fc925e2d33b3ca6f9d3908008e456725a8f2cf1
Now, you can use podman images
to view the image we've just downloaded.
# podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/mariadb 10.5 76a5b2d8081a 3 weeks ago 399 MB
This is because container filesystems are ephemeral, meaning once the container is removed, all the data associated with it is lost, we'll create a new volume to hold database data. Then, if we don't already have mysql
to work with the data in MariaDB, we can also install it using yum
.
# podman volume create mariadb_data mariadb_data # yum install -y mysql Installed: mariadb-connector-c-config-3.2.6-1.el9_0.noarch mysql-8.0.32-1.el9_2.x86_64 mysql-common-8.0.32-1.el9_2.x86_64 Complete!
And finally, let's run this container, running Podman with the following flags: -d for detached mode (in the background), -e
for setting environment variables, -p
for port assignment, -v
to route the volumes, and use the previously downloaded MariaDB image.
# podman run --name mariadb -e MYSQL_ROOT_PASSWORD=pass -p 3306:3306 -v mariadb_data:/var/lib/mysql -d docker.io/library/mariadb:10.5 00388490e13e9cb64b4f79ff4a56d250b725b67190e450251adbe3649cc280c2
Now, we can list the current running containers with podman ps
.
# podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 00388490e13e docker.io/library/mariadb:10.5 mysqld 25 seconds ago Up 26 seconds 0.0.0.0:3306->3306/tcp mariadb
As you can see, the container is up and running, but what is it doing? Let's check using podman logs
, and doing a grep
with head
to see the most recent activity in the logs.
# podman logs 00388490e13e | head 2023-06-08 18:10:09+00:00 [Note] [Entrypoint]: Entrypoint script for MariaDver 1:10.11.3+maria~ubu2204 started.B Server 1:10.11.3+maria~ubu2204 started. 2023-06-08 18:10:10+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' 2023-06-08 18:10:10+00:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:10.11.3+maria~ubu2204 started. 2023-06-08 18:10:10+00:00 [Note] [Entrypoint]: Initializing database files
Ah! It just started and has initialized its database. Now, to get the IP address of the container and connect to it using TCP, we can use a podman inspect
command.
# podman inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mariadb 10.88.0.10
Perfect, now we can run the mysql
client using the server address like so, and using the password pass
we set when running this MariaDB container.
# mysql -h 10.88.0.10 -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.5.5-10.5.20-MariaDB-1:10.5.20+maria~ubu2004 mariadb.org binary distribution
Within the MariaDB container, we can run regular commands that we would on any MySQL server.
mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+ mysql> CREATE DATABASE test; Query OK, 1 row affected mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+
Perfect. With everything looking good, we can exit the MariaDB server.
mysql> exit; Bye
Once finished with it's usage, we can also kill the container with podman kill, and destroy it as well.
# podman kill mariadb mariadb # podman rm mariadb mariadb
Doing a quick podman ps
, we can see there are no running containers, but let's start a new container to check for data persistence:
# podman run --name mariadb -e MYSQL_ROOT_PASSWORD=pass -p 3306:3306 -v mariadb_data:/var/lib/mysql -d docker.io/library/mariadb:10.5
Now, we can check to see if the container has started again.
# podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f854d9bdfa38 docker.io/library/mariadb:10.5 mysqld 4 seconds ago Up 4 seconds 0.0.0.0:3306->3306/tcp mariadb
Being a new container, we'll again need to get the IP address of the container and connect to it.
# podman inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mariadb 10.88.0.11
Let's go ahead and check the MariaDB server again to ensure our database persisted through the removal of the container earlier, using password pass
.
# mysql -h 10.88.0.11 -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.5.5-10.5.20-MariaDB-1:10.5.20+maria~ubu2004 mariadb.org binary distribution Copyright (c) 2000, 2023, Oracle and/or its affiliates. mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ mysql> exit; Bye
Great! Looks like our data has persisted, and the new database still is showing through the new container provision. Let's now stop and kill the container to tidy up.
# podman kill f854d9bdfa38 f854d9bdfa38
Manage containers as system services through systemd and Podman
Finally, we'll create a simple systemd
resource for handling the previously created MariaDB container, which will allow your system to manage your Podman container just like any other system service.
First, we need to create a systemd
resource file for handling the brand new container service.
# vim /etc/systemd/system/mariadb-container.service
Then, we'll paste the following content into the file. This simple service definition will attempt to remove an existing mariadb
container before starting a new one, and is configured to always restart the service if it stops.
[Unit] Description=MariaDB Podman container After=network.target [Service] Type=simple TimeoutStartSec=5m ExecStartPre=-/usr/bin/podman rm "mariadb" ExecStart=/usr/bin/podman run --name mariadb -e MYSQL_ROOT_PASSWORD=pass -p 3306:3306 -v mariadb_data:/var/lib/mysql -d docker.io/library/mariadb:10.5 ExecStop=/usr/bin/podman stop "mariadb" Restart=always RestartSec=30 [Install] WantedBy=multi-user.target
Save and close the file by selecting esc then :wq
, then we can reload the systemd
catalog and start the service.
# systemctl daemon-reload # systemctl start mariadb-container
Let's view the status of the service as well.
# systemctl status mariadb-container ● mariadb-container.service - MariaDB Podman container Loaded: loaded (/etc/systemd/system/mariadb-container.service; dis> Active: deactivating (stop) since Thu 2023-06-08 19:08:29 UTC; 4s > Process: 4910 ExecStartPre=/usr/bin/podman rm mariadb (code=exited,> Process: 4919 ExecStart=/usr/bin/podman run --name mariadb -e MYSQL> Main PID: 4919 (code=exited, status=0/SUCCESS); Control PID: 5004 (p> Tasks: 8 (limit: 48881) Memory: 18.6M CPU: 373ms CGroup: /system.slice/mariadb-container.service ├─5000 /usr/bin/conmon --api-version 1 -c 56cef5dded60b040> └─5004 /usr/bin/podman stop mariadb
Let's go ahead and stop the service for now, we can also use the command systemctl enable mariadb-container
to start it automatically at boot.
# systemctl stop mariadb-container
Awesome! We just set up a custom system service based on a container managed through Podman.
Further resources
Do you want an easy and fast way to experiment with Podman? Our self-paced interactive labs are the answer. Try out the lab on how to deploy a container using Podman, or more labs on building and deploying with RHEL.
To get a better understanding of Podman, check out these other related articles:
- What is Podman? (Red Hat)
- Podman basics: Resources for beginners and experts (Red Hat Developer Editorial Team)
- What is Podman Desktop? A developer's introduction (Ian Lawson)