How to install and use Podman in Ubuntu

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 Ubuntu 20.04 and latest versions of Ubuntu.

# Prerequisites

To follow along, ensure that you have the following:

  • An updated Ubuntu Server/Workstation
  • 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

# 1. Ensuring that the server is up to date

Use this command to ensure that our server packages are updated

sudo apt update && sudo apt upgrade -y

Let us ensure common packages are installed

sudo apt install -y vim wget

# 2. Installing Podman

# Installing Podman in Ubuntu 20.04

The Kubic project provides packages for active Ubuntu releases 20.04 and newer.

Access your ubuntu server and run following command to source release version.

source /etc/os-release

Execute following command to create apt source file

sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"

Add the apt key using following command:

wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_${VERSION_ID}/Release.key -O- | sudo apt-key add -

Now update Ubuntu repository using following command to enable Podman repository.

sudo apt update -qq

Finally use following command to install Podman

sudo apt-get -qq --yes install podman

Podman Package is available in the official repositories for ubuntu 20.10 and newer. To install Podman on Ubuntu 20.10 and newer, run the following command:

Update Ubuntu repositories to latest index using following command:

$ sudo apt update

To install Podman package run the following command:

$ sudo apt-get -y install podman

It is recommended to use Buildah, Podman and Skopeo ONLY from EITHER the kubic repo OR the official Ubuntu repos. Mixing and matching may create unpredictable situations including installation failure.

To verify the version of Podman installed, run:

$ podman --version
podman version 3.3.1

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

# 3. Command line examples

Let us explore running Ubuntu Container using podman.

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

docker run -it ubuntu:21.10 sh

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

podman run -it <meta charset="utf-8">ubuntu:21.10 sh

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

$ podman run -it ubuntu:21.10 sh
Resolved "ubuntu" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/ubuntu:21.10...
Getting image source signatures
Copying blob ae6e1b672be6 done
Copying config 2dc51e04d7 done
Writing manifest to image destination
Storing signatures
# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 05:24 pts/0    00:00:00 sh
root           2       1  0 05:24 pts/0    00:00:00 ps -ef
# exit

To check the container status use podman ps command

$ podman ps -a
CONTAINER ID  IMAGE                           COMMAND     CREATED         STATUS                     PORTS       NAMES
0b973691eef9  docker.io/library/ubuntu:21.10  sh          49 seconds ago  Exited (0) 41 seconds ago              nice_wiles

To delete the container, use podman rm:

$ podman rm 0b973691eef9
0b973691eef908fd15b444efb65e158ebd6efd8be468b335ed5905c05b13194f

To list the images:

$ podman images
REPOSITORY                TAG         IMAGE ID      CREATED      SIZE
docker.io/library/ubuntu  21.10       2dc51e04d744  11 days ago  79.9 MB

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

$ podman image rm ubuntu:21.10
Untagged: docker.io/library/ubuntu:21.10
Deleted: 2dc51e04d7445a7328ec97d88c4d68407d239b51f2b5dc0bd84036c3288da9b0

From the above, we can confirm that the podman command 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.0-alpine image

$ podman pull docker.io/library/postgres:14.0-alpine
Trying to pull docker.io/library/postgres:14.0-alpine...
Getting image source signatures
Copying blob a0d0a0d46f8b done
Copying blob 82e9eb77798b done
Copying blob 5034a66b99e6 done
Copying blob ccd761727716 done
Copying blob 3da258773353 done
Copying blob c6b2245b2f36 done
Copying blob 2c7ee7bc69e8 done
Copying blob 028554d3b6cc done
Copying config 87440f4e7f done
Writing manifest to image destination
Storing signatures
87440f4e7f9e60607dc11a4f0590a1c69b3a1c075211df478e22b0c27fb263e6

Confirm images

$ podman images
REPOSITORY                  TAG          IMAGE ID      CREATED      SIZE
docker.io/library/postgres  14.0-alpine  87440f4e7f9e  2 weeks ago  198 MB

Inspect the image with

$ podman inspect <meta charset="utf-8">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 \
    -e POSTGRES_PASSWORD=Sup3rSecre7 \
    -e POSTGRES_USER=citizix_user \
    -e POSTGRES_DB=citizix_db \
    docker.io/library/postgres:14.0-alpine

This is my output

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

Check processes:

$ podman ps
CONTAINER ID  IMAGE                                   COMMAND     CREATED        STATUS            PORTS                   NAMES
d0f2ad0fdc27  docker.io/library/postgres:14.0-alpine  postgres    3 seconds ago  Up 4 seconds ago  0.0.0.0:5432->5432/tcp  hopeful_khorana

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

$ podman logs d0f2ad0fdc27 | head
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
performing post-bootstrap initialization ... sh: locale: not found
2021-11-16 05:27:35.340 UTC [26] WARNING:  no usable system locales were found

Let us connect to the database and do some operations

$ podman exec -it <meta charset="utf-8">d0f2ad0fdc27 /bin/bash
bash-5.1# psql -U citizix_user -d citizix_db;
psql (14.0)
Type "help" for help.

citizix_db=# select version();
                                                   version
--------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.0 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&nbsp;to list. To complately remove it then podman rm -f.

$ $ podman kill d0f2ad0fdc27
d0f2ad0fdc27

$ podman ps -a
CONTAINER ID  IMAGE                                   COMMAND     CREATED             STATUS                       PORTS                   NAMES
d0f2ad0fdc27  docker.io/library/postgres:14.0-alpine  postgres    About a minute ago  Exited (137) 47 seconds ago  0.0.0.0:5432->5432/tcp  hopeful_khorana

$ podman rm -f d0f2ad0fdc27
d0f2ad0fdc2768882b82fb62990ee4b75a657b8e884dc192413d45dc8f44af14

# 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/ubuntu/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.0-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: enabled)
     Active: active (running) since Tue 2021-11-16 08:30:29 EAT; 35s ago
    Process: 60871 ExecStartPre=/usr/bin/podman rm -f postgrespodman (code=exited, status=1/FAILURE)
   Main PID: 60901 (podman)
      Tasks: 11 (limit: 4631)
     Memory: 245.7M
     CGroup: /system.slice/postgres-podman.service
             ├─60901 /usr/bin/podman run -p 5432:5432 -v /home/ubuntu/apps/postgres/data:/var/lib/postgresql/data:Z -e POSTGRES_PASSWORD=Sup3rSecre7 -e POSTGRES_USER=citizix_user -e POSTGRES_DB=citizix_d>
             └─61098 /usr/libexec/podman/conmon --api-version 1 -c c0f2d6e1dc998394f323f2dd2936e920c38b5d191d2342fbe3406cbfc715c7a8 -u c0f2d6e1dc998394f323f2dd2936e920c38b5d191d2342fbe3406cbfc715c7a8 -r >

Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.062 UTC [1] LOG:  starting PostgreSQL 14.0 on x86_64-pc-linux-musl, compiled by gcc (Alpine 10.3.1_git20210424) 10.3.1 2021042>
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.062 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.062 UTC [1] LOG:  listening on IPv6 address "::", port 5432
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.066 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.070 UTC [17] LOG:  database system was interrupted; last known up at 2021-11-16 05:27:36 UTC
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.098 UTC [17] LOG:  database system was not properly shut down; automatic recovery in progress
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.104 UTC [17] LOG:  redo starts at 0/16FAD98
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.104 UTC [17] LOG:  invalid record length at 0/16FADD0: wanted 24, got 0
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.104 UTC [17] LOG:  redo done at 0/16FAD98 system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
Nov 16 08:30:37 ubuntu-client.citizix.com podman[60901]: 2021-11-16 05:30:37.123 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 Ubuntu server in this guide.

comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy