Have you started a journey of learning and mastering containerization technologies?, did you stumble upon Podman in your research of the “best container management engines”?. Podman is a free to use application that can manage containers and pods. With its powerful command line interface you can build, find, run, and manage the overall lifecycle of containers. Podman is has gained lots of traction as a better secure alternative to Docker. But unlike docker, podman doesn’t require a daemon process running in the background.

Podman was originally build from the foundations of containerd, and with compliance to Open Container Initiative (OCI) standards. It has support for the following container related functionalities:

  • Container Image Management: Use podman to build container images, push to registry, or pull from registry.
  • Running of containerized applications: The run subcommand is used to run container from image, enter its shell, and manage an application in the container
  • Storage Management: Podman allows you to create persistent volumes, attach to container, and delete volumes.
  • Network Management: Podman gives you commands to manage container networking. Creating network bridge, and attaching the network to the application.
  • Pod Management: Podman primary focus is not pods management, but it enables you to manage group of containers as pods. This is similar to the functionality you get in Kubernetes.

What this article entails:

  • How to install podman on Ubuntu 24.04
  • How to build docker image using Dockerfile
  • How to run containers in Podman
  • How to mount external storage in Podman container
  • How to run pods in Podman
  • How to create a network in Podman and use with your containers

1 – Install Podman on Ubuntu 24.04

Update packages list in your Ubuntu system.

sudo apt update

Install Podman using apt package management tool available on Ubuntu.

sudo apt install podman -y

Installation only take few seconds.

Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  aardvark-dns buildah catatonit conmon containernetworking-plugins crun fuse-overlayfs golang-github-containers-common golang-github-containers-image libslirp0 libsubid4 libyajl2 login netavark
  passt passwd slirp4netns uidmap
Suggested packages:
  containers-storage libwasmedge0 docker-compose
The following NEW packages will be installed:
  aardvark-dns buildah catatonit conmon containernetworking-plugins crun fuse-overlayfs golang-github-containers-common golang-github-containers-image libslirp0 libsubid4 libyajl2 netavark passt
  podman slirp4netns uidmap
The following packages will be upgraded:
  login passwd
2 upgraded, 17 newly installed, 0 to remove and 187 not upgraded.
Need to get 33.4 MB of archives.
After this operation, 130 MB of additional disk space will be used.
Get:1 http://ke.archive.ubuntu.com/ubuntu noble/main amd64 login amd64 1:4.13+dfsg1-4ubuntu3 [202 kB]
Get:2 http://ke.archive.ubuntu.com/ubuntu noble/main amd64 passwd amd64 1:4.13+dfsg1-4ubuntu3 [845 kB]
Get:3 http://ke.archive.ubuntu.com/ubuntu noble/universe amd64 netavark amd64 1.4.0-4 [1,666 kB]
8% [3 netavark 1,217 kB/1,666 kB 73%]
... 

2 – Build your application using Dockerfile

Validate the installation of Podman by checking its version.

$ podman --version
podman version 4.9.3

Let’s build Nginx web server image using Dockerfile. Create a new file called Dockerfile

vim Dockerfile

Add the contents below – If you have a Dockerfile for your own specific application use it instead.

FROM ubuntu
MAINTAINER Josphat Mutai <[email protected]>

RUN apt update
RUN apt install nginx -y
RUN echo "Hello World from Podman" > /var/www/html/index.html

EXPOSE 80
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

Build your container image using podman build command.

podman build -t nginx:latest .

This will download Ubuntu base image, install nginx package, create simple hello world web page, and set port where the service will run to 80.

....
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of start.
Setting up nginx (1.18.0-6ubuntu14.4) ...
Processing triggers for libc-bin (2.35-0ubuntu3.6) ...
--> 10af6f97e841
STEP 5/7: RUN echo "Hello World from Podman" > /var/www/html/index.html
--> 5f7aff2e1220
STEP 6/7: EXPOSE 80
--> b506f58bddca
STEP 7/7: CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
COMMIT nginx:latest
--> 4bf25c100a11
Successfully tagged localhost/nginx:latest
4bf25c100a116551b0d727e827d560357f6a5edc15265e2fb7805f16677e2ecc

After the build, confirm by listing available container images.

$ podman images
REPOSITORY                TAG         IMAGE ID      CREATED         SIZE
localhost/nginx           latest      4bf25c100a11  40 seconds ago  188 MB
docker.io/library/ubuntu  latest      7af9ba4f0a47  10 days ago     80.4 MB

3 – Run containerized application in container

We have a container image which can be used to create a running instance of the application – this is a container. You can create container using the podman run commands.

podman run -d -p 8080:80 --name nginx  localhost/nginx

The -d flag will instruct podman to run the container in the background and detached, -p 8080 binds the service on your local host port number 8080. The container will have a name nginx.

List running Podman containers in the system.

$ podman ps
CONTAINER ID  IMAGE                   COMMAND               CREATED        STATUS        PORTS                 NAMES
40c59fdad9ae  localhost/nginx:latest  /usr/sbin/nginx -...  3 seconds ago  Up 3 seconds  0.0.0.0:8080->80/tcp  nginx

Access the web page of the application on the server IP port 8080.

Podmain on Ubuntu 01

The curl command can also be used to test application functionality from CLI.

$ curl http://192.168.1.201:8080/
Hello World from Podman

4 – Mount external storage in Podman container

If you delete a container, all the data stored in it is lost. To persist the data, an external storage is required. We can look at some options available for this.

1. Using Local directory

As an example we are creating a directory under /data

mkdir -p ~/data/container
echo "Test file for container data persistence"|tee ~/data/container/test.txt

To mount the directory in the container, run:

$ podman run -it -v ~/data/container:/mnt ubuntu /bin/bash
root@ebd6efbb01bf:/# cat  /mnt/test.txt
Test file for container data persistence

2. Using Podman Volumes

Podman volumes stores data inside the /var/lib/containers/storage/volumes/ directory. Let’s create a test volume to test this.

podman volume create testvolume

You can inspect created volume to see it’s mount point.

jkmutai@ubuntu-2404-server:~$ podman volume ls
DRIVER      VOLUME NAME
local       testvolume

jkmutai@ubuntu-2404-server:~$ podman volume inspect testvolume
[
     {
          "Name": "testvolume",
          "Driver": "local",
          "Mountpoint": "/home/jkmutai/.local/share/containers/storage/volumes/testvolume/_data",
          "CreatedAt": "2024-04-21T13:13:47.175944787Z",
          "Labels": {},
          "Scope": "local",
          "Options": {},
          "MountCount": 0,
          "NeedsCopyUp": true,
          "NeedsChown": true,
          "LockNumber": 3
     }
]

To mount the volume use the commands below.

$ podman run -it -v testvolume:/mnt ubuntu /bin/bash

Validate by listing mount points in the container.

root@8bf46bd77811:/# df -hT
Filesystem                        Type     Size  Used Avail Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv ext4      15G  5.7G  8.3G  41% /mnt
tmpfs                             tmpfs    392M  184K  392M   1% /etc/hosts
shm                               tmpfs     63M     0   63M   0% /dev/shm
overlay                           overlay   15G  5.7G  8.3G  41% /
tmpfs                             tmpfs     64M     0   64M   0% /dev

To delete the volume run:

podman volume rm testvolume

3. NFS File systems

Create a volume with NFS access information.

podman volume create \
--opt type=nfs4 \
--opt o=rw \
--opt device=192.168.1.22:/nfsshare nfsvolume 

Where;

  • 192.168.1.22 is the IP address of your NFS server
  • /nfsshare is the exported path on NFS share – NFS share.

Now mount the volume in container like any other volumes.

 podman run -it -v nfsvolume:/nfsshare ubuntu

5 – How to run pods in Podman

Create a pod whose services will be on port 8085

podman pod create -p 8085:80 -n mypod

List created pods.

$ podman pod ls
POD ID        NAME        STATUS      CREATED        INFRA ID      # OF CONTAINERS
fd73821c2dbb  mypod       Created     5 seconds ago  aaacb992072e  1

You can then create a container inside the pod.

podman run -dt --pod mypod localhost/nginx

See running containers

$ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED             STATUS         PORTS                 NAMES
aaacb992072e  localhost/podman-pause:4.9.3-0                        About a minute ago  Up 19 seconds  0.0.0.0:8085->80/tcp  fd73821c2dbb-infra
e3d2331926fc  localhost/nginx:latest          /usr/sbin/nginx -...  19 seconds ago      Up 19 seconds  0.0.0.0:8085->80/tcp  heuristic_tu

Test service.

$ curl localhost:8085
Hello World from Podman

We create multiple containers, e.g running Nginx and MySQL like below.

podman run -dt --pod new:mypod2 -p 8086:80 -p 3306:3306 localhost/nginx
podman run -dt --pod mypod2 -e MYSQL_ROOT_PASSWORD=DBPassword docker.io/library/mariadb

List containers

$ podman ps
CONTAINER ID  IMAGE                             COMMAND               CREATED             STATUS             PORTS                                         NAMES
aaacb992072e  localhost/podman-pause:4.9.3-0                          7 minutes ago       Up 6 minutes       0.0.0.0:8085->80/tcp                          fd73821c2dbb-infra
e3d2331926fc  localhost/nginx:latest            /usr/sbin/nginx -...  6 minutes ago       Up 6 minutes       0.0.0.0:8085->80/tcp                          heuristic_tu
54c1f7f605af  localhost/podman-pause:4.9.3-0                          About a minute ago  Up About a minute  0.0.0.0:3306->3306/tcp, 0.0.0.0:8086->80/tcp  1f3c516682fc-infra
38aec09c76dc  localhost/nginx:latest            /usr/sbin/nginx -...  About a minute ago  Up About a minute  0.0.0.0:3306->3306/tcp, 0.0.0.0:8086->80/tcp  competent_easley
543ebb2a4874  docker.io/library/mariadb:latest  mariadbd              26 seconds ago      Up 26 seconds      0.0.0.0:3306->3306/tcp, 0.0.0.0:8086->80/tcp  lucid_nash

Test usability.

$ curl localhost:8086
Hello World from Podman

$ mysql -u root -p'DBPassword' -h 192.168.1.201 -e "show variables like 'hostname';"
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| hostname      | mypod2 |
+---------------+--------+

6 – Creating Podman network

To create a new network with subnet 172.20.50.0/24 use:

podman network create --subnet 172.20.50.0/24 network50

Attaching it to the container.

podman run --network network50 ubuntu /bin/bash

You can connect network to running container

 podman network connect <networkname> <container>

To disconnect use:

 podman network disconnect <networkname> <container>

Checking routes in the container

 podman exec <container> /bin/bash -c "apt update; apt -y install iproute2; ip route"
podman exec <container> ip route

To completely delete the network use:

podman network ls
podman network rm <networkname>
podman network rm -f <networkname>

Refer to Podman Documentation for more practical usage examples of Podman.

LEAVE A REPLY

Please enter your comment!
Please enter your name here