How to Install and Use Podman

Feb 13, 2024 · 11 mins read
How to Install and Use Podman

In the video below, we show you how to install and use Podman


Docker is a very popular platform for containers but there’s one thing that concerns me about it…containers are run using the root account

Now the developers did make it possible to run containers using a non-root account, but that’s not part of the default installation process

So why not use another platform like Podman?

Well what sets Podman apart is that it’s daemonless and its default installation makes running containers more secure

And in this video we’ll go over how to install Podman and use it to run containers

Useful links:
https://podman.io/docs/installation

Installation
Installing Podman on a Debian distro is as simple as it gets , but it’s best to first update the package repository cache

sudo apt update
sudo apt install podman -y

Although the instructions don’t mention it, I suggest rebooting the computer

sudo reboot now

If you don’t you’ll probably get error messages like this when you try to use Podman commands:
“The cgroupv2 manager is set to systemd but there is no systemd user session available”

Run Containers
Using Podman is very similar to what you do with Docker

For example, to run Apache in a container we can run a command like this

podman run -d -p 8080:80/tcp --name webserver docker.io/library/httpd

This will download the image for the httpd server, aka Apache web server, and run it in a container in the background on the familiar port 8080

And then we can check if it’s working using a web browser, or do a basic check on the computer using this command

curl http://localhost:8080

You can check which containers exist with this command

podman ps -a

To stop a container we can run this command

podman stop webserver

Hopfully, you’re now noticing the similarity with Docker

Security:
Now as I mentioned in the intro, one of the concerns with Docker is that with a default installation, containers are run using the root account

Now you might notice various documentation out there about how to set up Podman to run rootless containers

What we’ve done here though is just a default installation

First, lets start our web server back up

podman run -d -p 8080:80/tcp --name webserver docker.io/library/httpd

Now as you’ll see we run into a problem because a container has already been run with the name we’ve specified

You don’t get this issue with Docker I’ve noticed, but for Podman we need to clear unused containers

podman container prune -f

Next we’re going to check what user is running this container

ps aux

As you can see, our webserver isn’t being run by root

NOTE: The first line of reference will likely mention the user account you’re logged in with, others will show up with just a number. This is because an account has a range of IDs it can use

We can also check what is being run with the root account for extra measure

ps -u root

Before we move on, we’ll stop this container

podman stop webserver

Then clear unused containers to avoid future warnings and errors

podman container prune -f

Podman Compose:
Like Docker, you may prefer to manage your containers from a file

To do that, we’ll first install podman-compose

sudo apt install podman-compose -y

As with Docker, we need to create a compose file

nano compose.yaml

TIP: It does recognise other filenames

For our Apache server we’ll add this

version: '3'

services:
  webserver:
    image: docker.io/library/httpd
    container_name: webserver
    ports:
      - '8080:80'
    restart: unless-stopped

Now save and exit

So basically it’s the same as for Docker because compose files are based on a standard

Then to start up any containers defined in the file, we’ll run this command

podman-compose up -d

In other words, we want to start up any containers that aren’t yet running, but in the background

Podman Build:
Just like with Docker you can build your own images, which is the recommended way to deploy containers

In this example, we’ll create an Apache web server image, so first we’ll create a folder and switch to it

mkdir myapache_image
cd myapache_image

Next we’ll create the dockerfile

nano Dockerfile

NOTE: With Podman the file must be capitilised, otherwise you’ll get an error message

Then we’ll provide the instructions

FROM httpd:latest
COPY ./public-html/ /usr/local/apache2/htdocs/

Now save and exit

For our image, we’ll use the Apache web server as our base image, but replace the webpage using the COPY command to upload our own content

As we need to provide our own webpage for this, we’ll create a sub-folder

mkdir public-html

Then create our webpage in that folder

nano public-html/index.html

But we’ll keep this web page simple

<html><body><h1>This Is My Web Server!</h1></body></html>

Now save and exit

We’ll then build the image

podman build -t myapache .

You can check what images you have by running this command

podman images

Before we can use this image in a container, we’ll stop the other one

podman stop webserver

And clear out unused containers

podman container prune -f

Now we’ll run a container using the image we just built

podman run -d -p 8080:80/tcp --name myapache myapache

Finally, we can check if it’s working using a web browser, or do a basic check on the computer using this command

curl http://localhost:8080

NOTE: You can’t run two applications or containers in this case on the same host port, hence why the original container was stopped. They containers can still use port 80 themselves, but the host would have to map one to port 8080 and another to 8081 for instance

Privileged Ports:
Although we have the security benefit of Podman running containers rootless, there’s a problem if you want to use ports below 1024

For instance, lets say we want our web server to be available on port 80

After all, most users aren’t used to having to add a port number in the URL

Well first we’ll switch back to the parent folder, stop our container, then remove unused containers

cd ..
podman stop myapache
podman container prune -f

Next we’ll tell Podman to use port 80 instead of 8080

podman run -d -p 80:80/tcp --name myapache myapache

As you see, we get an error message

This is a downside of running containers rootless, they can’t use ports below 1024

There are different ways to deal with this, but we’ll add a new file to the /etc/sysctl.d/ folder

TIP: We could update the /etc/sysctl.conf file, as the error suggested, but that could change in a future update

sudo nano /etc/sysctl.d/98-containers.conf

net.ipv4.ip_unprivileged_port_start=23

Now save and exit

I’ve set the lower limit to 23 as SSH uses port 22 and I don’t want to run into a possible overlap in future and not being able to get access to the host

For the changes to take effect we need to reload the configuration

sudo sysctl --system

TIP: You can do the same for Docker if you want to run that rootless

You should see the port change in the output, but you can check with this command

sudo sysctl -a | grep "net.ipv4.ip_unprivileged_port_start"

Here we’re filtering out the parameter settings to just see information about what the lower port limit is

We’ll first stop our container

podman stop myapache

Then because Podman seems to be more fussy than Docker, remove unused containers

podman container prune -f

And then run our container again

podman run -d -p 80:80/tcp --name myapache myapache

Finally, we can check if it’s working using a web browser, or do a basic check on the computer using this command

curl http://localhost

The change does survive a reboot, so unless you need to lower the port level in future, no further changes should be necessary

Before we move on though, we’ll stop this container and clear unused containers

podman stop myapache
podman container prune -f

Manually Update Images:
Usually you’ll want to use the latest version of an image

And when you first run a container and ask for the latest version, the latest version will be download

Over time that image will become out of date though, so you’ll want to update it

You can find out what images are on your computer by running this command

podman images

If a container is running an image you want to update, you’ll want to stop it first, for example

podman ps
podman stop webserver

To manually update a specific image you can run a command like this

podman pull docker.io/library/httpd

Or if you’re using podman-compose you can use this command to update the images mentioned in a compose file

podman-compose pull

But again, you do need to stop the containers before updating the images

Podman Service:
The main appeal of Podman is that it runs containers using a non-root account

But that comes at a cost, because when the computer reboots your containers aren’t automatically started

To resolve this you need to create a service to run your Podman containers

Now how you do this depends on how you’re running your containers

A service for each individual container doesn’t seem practical to me, so either a script could be used or in this example we’ll run podman-compose

First we’ll create a new user account

sudo useradd -m -s /bin/bash podmanuser

The we’ll switch to that user account and switch to the home directory

sudo su podmanuser
cd

Next we’ll re-create our compose.yaml file to define our containers

nano compose.yaml

version: '3'

services:
  webserver:
    image: docker.io/library/httpd
    container_name: webserver
    ports:
      - '8080:80'
    restart: unless-stopped

Now save and exit

We’ll now switch back to our normal account

exit

Next we’ll create the service file

sudo nano /lib/systemd/system/podman-compose.service

[Unit]
Description=Podman-compose
Wants=network-online.target
After=network-online.target

[Service]
User=podmanuser
Group=podmanuser
Type=oneshot
RemainAfterExit=true
ExecStartPre=/usr/bin/podman system prune -f
ExecStart=/usr/bin/podman-compose -f /home/podmanuser/compose.yaml up -d
ExecStop=/usr/bin/podman-compose down

[Install]
WantedBy=default.target

Now save and exit

To tray and avoid problems, we’ll have Podman clear any used data first, in case there isn’t a clean shutdown for instance

The it will run podman-compose to bring up the containers

When the service is shutdown, it will tear down the containers

As we’ve created a new service, we’ll update the system, enable it to start on boot and then start the service

sudo systemctl --system daemon-reload
sudo systemctl enable podman-compose.service
sudo systemctl start podman-compose.service

Bear in mind, it does take a while to start the service for the first time because it will have to download the image(s)

This is because Podman is used on a per user basis and each user has their own storage area

But once we’re returned to the prompt, we can check if it’s working using a web browser, or do a basic check on the computer using this command

curl http://localhost:8080

One final check will be to reboot the computer and check again

sudo reboot now

Summary:
Hopfully as you can see, it’s relatively easy to setup and run rootless containers using Podman

The catch is if you’re only using Podman to run containers, and you want these to survive a reboot for instance

Then you’ll want to setup a service account to automatically start them

Now if you prefer to use a graphical user interface over a CLI to manage containers, then you can install Podman Dekstop to do that

One thing I haven’t touched on mind, and something you may want to explore, is Podman also allows you to group containers into a pod

So aside from the security benefits, and the simpler installation process, I think that’s another benefit that Podman has to offer over Docker

Sharing is caring!