How to install and use Podman in Rocky/Alma Linux 9

Podman is a container engine that’s compatible with the OCI Containers specification. It is part of RedHat Linux, but can also be installed on other distributions. As it’s OCI-compliant, Podman can be used as a drop-in replacement for the better-known Docker runtime. Most Docker commands can be directly translated to Podman commands. Podman implements almost all the Docker CLI commands (apart from the ones related to Docker Swarm). 

Podman complements Buildah and Skopeo by offering an experience similar to the Docker command line: allowing users to run standalone (non-orchestrated) containers. And Podman doesn’t require a daemon to run containers and pods, so we can easily say goodbye to big fat daemons. There are no daemons in the background doing stuff, and this means that Podman can be integrated into system services through systemd.

In this guide we will learn how to install Podman in Rocky/Alma Linux 9. This post also works for RHEL 8 derivatives such as Oracle Linux.

Prerequisites

To follow along, ensure that you have the following:

  • An updated Rocky Linux 9
  • Root access or User with sudo access
  • Access to the internet

Table of content

  1. Ensuring that the server is up to date
  2. Installing podman
  3. Command line examples
  4. Run a postgres persistent container
  5. Managing containers as system services through systemd and Podman

1. Ensuring that the server is up to date

Use this command to ensure that our server packages are updated

sudo dnf update -y

Let us ensure common packages are installed

sudo dnf install -y vim

2. Installing Podman

Podman is available in the default AppStream repo for Rocky Linux 9. Install it using this command:

sudo dnf install -y podman

This command will install Podman and also its dependencies: atomic-registriesrunCskopeo-containers, and SELinux policies.

That’s all. Now we can now play with Podman.

3. Command line examples

Let us explore running Rocky Linux Container using podman.

On docker we would use this command to run a rocky linux container:

docker run -it rockylinux/rockylinux:9.0 sh

This will fail since there is no docker command on my Rocky Linux Server. We can replace docker with podman:

podman run -it rockylinux/rockylinux:9.0 sh

Let us run some commands to confirm that it is working as expected:

$ podman run -it rockylinux/rockylinux:9.0 sh
✔ docker.io/rockylinux/rockylinux:9.0
Trying to pull docker.io/rockylinux/rockylinux:9.0...
Getting image source signatures
Copying blob e6e95ffe6dbe done
Copying config 4c29982749 done
Writing manifest to image destination
Storing signatures
sh-5.1# whoami
root
sh-5.1# exit
exit

To check the container status use podman ps command

$ podman ps -a
CONTAINER ID  IMAGE                                COMMAND     CREATED         STATUS                     PORTS       NAMES
d8b968441ab9  docker.io/rockylinux/rockylinux:9.0  sh          56 seconds ago  Exited (0) 23 seconds ago              hopeful_panini

To delete the container, use podman rm:

$ podman rm d8b968441ab9
d8b968441ab9b7d95929ed987d9c8c84880fa1eb280315323e4152cf55b86f1c

To list the images:

$ podman images
REPOSITORY                       TAG         IMAGE ID      CREATED       SIZE
docker.io/rockylinux/rockylinux  9.0         4c29982749ec  2 months ago  205 MB

We can delete the image using the image podman image rm command:

$ podman image rm rockylinux/rockylinux
Untagged: docker.io/rockylinux/rockylinux:9.0
Deleted: 333da17614b642a228c30edcb2bddfdf17b2d713ae71b7930c44b714ff8b92e7

From the above, we can confirm that the podman commandn uses the same syntax as docker

Run a Postgres persistent container

Next, let us explore how we can run a persistent container. In this example, we are going to run a Postgres 14 container and mount the postgres data to a local volume so it can persist restarts. Since containers are ephimeral, data will be lost if we do not save in a local volume.

Pull docker.io/library/postgres:14.5-alpine image

$ podman pull docker.io/library/postgres:14.5-alpine
Trying to pull docker.io/library/postgres:14.5-alpine...
Getting image source signatures
Copying blob 85c3ef7cf9a6 done
Copying blob ac29cc04759a done
Copying blob 2a37e244d86b done
Copying blob 36d7202aa1cf done
Copying blob 3acdddb9790a done
Copying blob 213ec9aee27d done
Copying blob 9a938759f2bf done
Copying blob 5d65a6241248 done
Copying config a762fe0bf5 done
Writing manifest to image destination
Storing signatures
a762fe0bf572269925c14b2eefb2b24c60ab768a37be124e9eff45fd41c72e7f

Confirm images

$ podman images
REPOSITORY                       TAG          IMAGE ID      CREATED       SIZE
docker.io/library/postgres       14.5-alpine  a762fe0bf572  6 weeks ago   220 MB
docker.io/rockylinux/rockylinux  9.0          4c29982749ec  2 months ago  205 MB

Inspect the image with

$ podman inspect 87440f4e7f9e

Let’s set up a folder that will handle Postgres data once we start our container:

$ mkdir -p ~/apps/postgres/data

Run it

podman run -d \
    -p 5432:5432 \
    -v ~/apps/postgres/data:/var/lib/postgresql/data:Z \
    -e POSTGRES_PASSWORD=Sup3rSecre7 \
    -e POSTGRES_USER=citizix_user \
    -e POSTGRES_DB=citizix_db \
    docker.io/library/postgres:14.5-alpine

This is my output

$ podman run -d \
>     -p 5432:5432 \
>     -v ~/apps/postgres/data:/var/lib/postgresql/data:Z \
>     -e POSTGRES_PASSWORD=Sup3rSecre7 \
>     -e POSTGRES_USER=citizix_user \
>     -e POSTGRES_DB=citizix_db \
>     docker.io/library/postgres:14.5-alpine
9aa1fb68beeeb7c68a9ea5afb4ca91bf07acf3fef92bf21249a6d8a4e43f5dbd

Check processes:

$ podman ps
CONTAINER ID  IMAGE                                   COMMAND     CREATED         STATUS             PORTS                   NAMES
9aa1fb68beee  docker.io/library/postgres:14.5-alpine  postgres    46 seconds ago  Up 47 seconds ago  0.0.0.0:5432->5432/tcp  gracious_jemison

Confirm the container logs with this. You can see that it is initializing the db

$ podman logs 9aa1fb68beee | head
performing post-bootstrap initialization ... sh: locale: not found
2021-11-11 09:05:00.481 UTC [30] WARNING:  no usable system locales were found
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data ... ok

Let us connect to the database and do some operations

$ podman exec -it 9aa1fb68beee /bin/bash
bash-5.1# psql -U citizix_user -d citizix_db;
psql (14.5)
Type "help" for help.

citizix_db=# select version();
                                                   version
--------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.5 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.3.1_git20210424) 10.3.1 20210424, 64-bit
(1 row)

citizix_db=#

Next let us explore killing and removing the container. We can use podman kill to stop the container. This will stop the container, but it will still be there. Use podman ps -a to list. To complately remove it then podman rm -f.

$ podman kill 9aa1fb68beee
9aa1fb68beee
$ podman ps -a
CONTAINER ID  IMAGE                                   COMMAND     CREATED         STATUS                       PORTS                   NAMES
9aa1fb68beee  docker.io/library/postgres:14.0-alpine  postgres    14 minutes ago  Exited (137) 20 seconds ago  0.0.0.0:5432->5432/tcp  gracious_jemison
$ podman rm -f 9aa1fb68beee
9aa1fb68beeeb7c68a9ea5afb4ca91bf07acf3fef92bf21249a6d8a4e43f5dbd

Managing containers as system services through systemd and Podman

We can manage podman containers through systemd. Let us create a systemd resource file for handling the postgres container we just created above.

Create a postgres podman file:

sudo vim /etc/systemd/system/postgres-podman.service

Add this content

[Unit]
Description=Custom Postgres Podman Container
After=network.target

[Service]
Type=simple
TimeoutStartSec=5m
ExecStartPre=-/usr/bin/podman rm -f postgrespodman

ExecStart=/usr/bin/podman run \
    -p 5432:5432 \
    -v /home/rocky/apps/postgres/data:/var/lib/postgresql/data:Z \
    -e POSTGRES_PASSWORD=Sup3rSecre7 \
    -e POSTGRES_USER=citizix_user \
    -e POSTGRES_DB=citizix_db \
    docker.io/library/postgres:14.5-alpine

ExecReload=-/usr/bin/podman stop postgrespodman
ExecReload=-/usr/bin/podman rm postgrespodman
ExecStop=-/usr/bin/podman stop postgrespodman
Restart=always
RestartSec=30

[Install]

Then we can reload the systemd catalog and start the service:

sudo systemctl daemon-reload
sudo systemctl start postgres-podman

Confirm the service status

$ sudo systemctl status postgres-podman
● postgres-podman.service - Custom Postgres Podman Container
   Loaded: loaded (/etc/systemd/system/postgres-podman.service; static; vendor preset: disabled)
   Active: active (running) since Thu 2021-11-11 10:07:09 UTC; 21s ago
  Process: 71868 ExecStop=/usr/bin/podman stop postgrespodman (code=exited, status=125)
  Process: 71943 ExecStartPre=/usr/bin/podman rm -f postgrespodman (code=exited, status=1/FAILURE)
 Main PID: 71973 (podman)
    Tasks: 11 (limit: 23167)
   Memory: 27.8M
   CGroup: /system.slice/postgres-podman.service
           ├─71973 /usr/bin/podman run -p 5432:5432 -v /home/rocky/apps/postgres/data:/var/lib/postgresql/data:Z -e POSTGRES_PASSWORD=Sup3rSecre7 -e POSTGRES_USER=citizix_user -e POSTGRE>
           └─72073 /usr/bin/conmon --api-version 1 -c 03e82c0f88fe4d69630b308f59f2e62bb23b19021a0de5ab0b267950c9367103 -u 03e82c0f88fe4d69630b308f59f2e62bb23b19021a0de5ab0b267950c9367103>

Nov 11 10:07:09 ip-10-2-40-72.us-west-2.compute.internal systemd[1]: Starting Custom Postgres Podman Container...
Nov 11 10:07:09 ip-10-2-40-72.us-west-2.compute.internal podman[71943]: Error: no container with name or ID "postgrespodman" found: no such container
Nov 11 10:07:09 ip-10-2-40-72.us-west-2.compute.internal systemd[1]: Started Custom Postgres Podman Container.
Nov 11 10:07:10 ip-10-2-40-72.us-west-2.compute.internal podman[71973]: PostgreSQL Database directory appears to contain a database; Skipping initialization
Nov 11 10:07:10 ip-10-2-40-72.us-west-2.compute.internal podman[71973]: 2021-11-11 10:07:10.428 UTC [1] LOG:  starting PostgreSQL 14.0 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10>
Nov 11 10:07:10 ip-10-2-40-72.us-west-2.compute.internal podman[71973]: 2021-11-11 10:07:10.429 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
Nov 11 10:07:10 ip-10-2-40-72.us-west-2.compute.internal podman[71973]: 2021-11-11 10:07:10.429 UTC [1] LOG:  listening on IPv6 address "::", port 5432
Nov 11 10:07:10 ip-10-2-40-72.us-west-2.compute.internal podman[71973]: 2021-11-11 10:07:10.432 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
Nov 11 10:07:10 ip-10-2-40-72.us-west-2.compute.internal podman[71973]: 2021-11-11 10:07:10.437 UTC [20] LOG:  database system was shut down at 2021-11-11 10:07:09 UTC
Nov 11 10:07:10 ip-10-2-40-72.us-west-2.compute.internal podman[71973]: 2021-11-11 10:07:10.440 UTC [1] LOG:  database system is ready to accept connections

We just set up a custom system service based on a container managed through Podman!

Conclusion

We managed to explore how to install Podman in our Rocky Linux 9 server in this guide.

Last updated on Oct 14, 2024 11:46 +0300
comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy