How to run and manage containers as systemd services with Podman

Linux containers are executable application components that combine app source code with operating system libraries and dependencies needed to run the code in different environments. Containers combine lightweight application isolation with the flexibility of image-based deployment methods. Developers use containers as an application packaging and delivery technology.

RHEL based systems (CentOS and Fedora Linux) implements containers using technologies such as namespaces for system process isolation, control groups for resource management, and SELinux for security management. Red Hat also provides command-line tools like podman, skopeo, and buildah to manage container images and pods.

This article illustrates how to run and manage containers as systemd services with podman. To get started, review our articles on introduction to Linux containers, managing containers with Podman, and managing systems units.

Podman

Podman is a tool for running Linux containers and is a powerful alternative to Docker.

The podman command can run and manage containers and images. Podman and docker support similar commands and features. The main difference is that podman is lightweight and doesn’t require an active container engine or a docker service for commands to work. In addition, Podman supports running containers in pods, and it fully integrates with systemd. The best attributes of Podman include:

  • Podman can run in rootless mode – its containers are more secure since they run without any added privileges.
  • Podman is daemonless- it has lower resource requirements at idle because if you are not running containers, Podman is not running. Docker, on the other hand, has a daemon always running.
  • systemd integration -it allows you to run containers as system services.

Installing Podman

You can install Podman in your distro from your package manager or build it from the source. Use the following command to install Podman.

On Fedora

sudo dnf -y install podman

Fedora-CoreOS, Fedora SilverBlue
Podman is built-in

On Arch Linux & Manjaro Linux

sudo pacman -S podman

On CentOS

sudo yum -y install podman

On openSUSE

sudo zypper install podman

On Debian

sudo apt-get -y install podman

On Ubuntu

sudo apt-get -y update
sudo apt-get -y install podman

On OpenSUSE

sudo zypper -n in libseccomp-devel libgpgme-devel

Podman commands

The following is a list of typical commands you can use with the podman command. You can use the – help command to find out how to work with Podman.

$ podman --help
$ podman <subcommand> --help
  • attach – Attach to a running container
  • commit – Create a new image from the changed container
  • build – Build an image using Container file instructions
  • create – Create, but do not start a container
  • diff – Inspect changes on container’s filesystems
  • exec – Run a process in a running container
  • export – Export container’s filesystem contents as a tar archive
  • images – List images in local storage
  • import – Import a tarball to create a filesystem image
  • kill – Send a specific signal to one or more running containers
  • mount – a working container’s root filesystem
  • pause – Pauses all the processes in one or more containers
  • ps – List containers
  • pull – an image from a registry
  • push – an image to a specified destination
  • restart – one or more containers
  • rm – remove one or more containers from the host.
  • rm -f – remove containers if running.
  • rmi – removes one or more images from local storage
  • run – a command in a new container
  • search – registry for image
  • start – one or more containers
  • stop – one or more containers
  • top – the running processes of a container
  • umount, unmount – a working container’s root filesystem
  • unpause – Unpause the processes in one or more containers
  • wait – Block on one or more containers

Systemd

System daemon or systemd is a service and system manager for Linux. It uses the systemctl command to manage system units that are representations of system services and resources. You can use it to enable or disable services permanently or for the current session.
You can use the systemd initialization service by either starting containers with systemd or starting services within a container.

Starting Containers with systemd

You can set up a systemd unit file on your host to automatically start, stop, check the status, and manage a container as a systemd service. It gives you options to define the order in which the containerized service runs, check for dependencies like initializing another service, mounting a resource, checking file availability, or starting a container using the runc command.

The following steps describe how to configure a container to run directly on a Fedora system as a systemd service.

Step 1: Get a Nginx image from the docker.io registry using the following command.

$ podman pull docker.io/nginx

Verify the image has been successfully pulled:

$ podman images

Step 2: Configure SELinux permission.
If SELinux is enabled on your host, use the following command to turn on the container_manage_cgroup boolean that enables you to run containers with systemd.

# setsebool -P container_manage_cgroup on

Step 3: Run the image as a container.
Run the container with a name that you will use to configure the systemd service file.

$ podman run -d --name fosslinux_nginx_server -p 7070:80 nginx

Verify that the container is running with the podman ps command.

$ podman ps
podman run
podman run  (fosslinux_nginx_server)

Step 4: Configure the container as a systemd service.
To create a container systemd service, create a configuration file in the /etc/systemd/system/ directory of your host.
Use the following command to create a unit file with the name [/etc/systemd/system/fosslinux_nginx_server.service]. Include the start and stop systemd service configuration options.

$ sudo vi /etc/systemd/system/fosslinux_nginx_server.service
[Unit]
Description=Nginx container
[Service]
Restart=always
ExecStart=/usr/bin/podman start -a fosslinux_nginx_server
ExecStop=/usr/bin/podman stop -t 2 fosslinux_nginx_server
[Install]
WantedBy=local.target

Note that name [fosslinux_nginx_server] in the unit file should match the name of the container that you set with the podman run command.

Step 5: Enable the container service to start automatically at boot.

# systemctl enable fosslinux_nginx_server.service
Created symlink /etc/systemd/system/multi-user.target.wants/fosslinux_nginx_server.service → /etc/systemd/system/fosslinux_nginx_server.service.

Once the Nginx container service is enabled, it will start automatically at boot.

Step 6: Start the service immediately and check its status.

# systemctl start fosslinux_nginx_server.service
# systemctl status fosslinux_nginx_server.service
* fosslinux_nginx_server.service - Nginx container
Loaded: loaded (/etc/systemd/system/fosslinux_nginx_server.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2022-02-17 15:22:55 EDT; 6s ago
Main PID: 1540 (podman)
Tasks: 8 (limit: 2353)
Memory: 7.7M
CGroup: /system.slice/fosslinux_nginx_server.service
└─1540 /usr/bin/podman start -a fosslinux_nginx_server

Porting containers to systemd

Podman is a versatile daemonless tool that can be managed in the same way services are managed in a Linux operating system. You can use the systemd to work with containers and pods. For example, you can use the podman generate systemd command to generate a systemd unit file for pods and containers. The systemd unit files can then provide portable descriptions of containers and pods.
You can then use the systemd unit files generated to:

  • Set up a container or pod to start as a systemd service.
  • Check for dependencies and define the order in which the containerized services run.
  • Control the state of the systemd system.

Enabling systemd services

To get started, enable the systemd service with the following commands:
To enable a service at system start, no matter if the user is logged in or not:
First, copy the systemd unit files to the /etc/systemd/system directory

# systemctl enable <service>

To start a service at user login and stop it at user logout:
First, copy the systemd unit files to the $HOME/.config/systemd/user directory.

$ systemctl --user enable <service>

To enable users to start a service at boot and persist over logouts:

# loginctl enable-linger <user>

Generating a systemd unit file using Podman

Podman allows systemd to manage container processes. You can use the podman generate systemd command to generate a systemd unit file for existing containers and pods. The command will enable you to get the latest version of unit files via updates to Podman.
Step 1: Create a container (foss_one).

@fedora ~]$ podman create --name foss_one docker.io/library/nginx:latest sleep infinity
205ce07ab9f54da8bb9b01f7be9ae61f0de8f7b3fdc47c178a9077a6a4d7a482

Step 2: Generate a systemd unit file and direct it to a service file (~/.config/systemd/user/container-foss_one.service):

@fedora ~]$ podman generate systemd --name fossone > ~/.config/systemd/user/container-fossone.service
podman generate systemd
podman generate systemd

Step 3: Verify by displaying the content of the generated unit file:

@fedora ~]$ cat ~/.config/systemd/user/container-fossone.service
# container-fossone.service
# autogenerated by Podman 3.4.4
# Sat Feb 19 14:37:42 EAT 2022 

[Unit]
Description=Podman container-fossone.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/run/user/1000/containers
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman start fossone
ExecStop=/usr/bin/podman stop -t 10 fossone
ExecStopPost=/usr/bin/podman stop -t 10 fossone
PIDFile=/run/user/1000/containers/overlay-containers/012dacab435e67fe4d99795a5f2ec2473d560071749a919abe21447e847949b5/userdata/conmon.pid
Type=forking
[Install]

Auto-generating a systemd unit file using Podman

Podman generates a unit file for each container or pod in your system. You can generate more portable systemd unit files using the podman generate systemd –new. It instructs Podman to generate unit files that create, start and remove containers.

Step 1: Pull an image (httpd):

@fedora ~]$ podman pull docker.io/library/httpd

Step 2: Create a container (httpd):

@fedora ~]$ podman create --name fosshttpd -p 8080:8080 docker.io/library/httpd
4a69fd86a953454497ab96d413118819b877d889356427ae414d9706095b1d0d

Verify the container has been created:

@fedora ~]$ podman

Step 3: Generate a systemd unit file for the container (httpd):

@fedora ~]$ podman generate systemd --new --files --name fosshttpd
/home/user/container-fosshttpd.service

Step 4: Display the content of the generated unit file (container-fosshttpd):

systemd service
systemd container service
@fedora ~]$ cat /home/user/container-fosshttpd.service
# container-fosshttpd.service
# autogenerated by Podman 3.4.4
# Sat Feb 19 15:01:59 EAT 2022
[Unit]
Description=Podman container-fosshttpd.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --sdnotify=conmon -d --replace --name fosshttpd -p 8080:8080 docker.io/library/httpd
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all
[Install]

Step 5: Copy unit files to /usr/lib/systemd/system to install as a root:

@fedora ~]$ sudo cp -Z container-fosshttpd.service /etc/systemd/system

Step 6: Enable and start the container-fosshttpd.service:

# systemctl daemon-reload
@fedora ~]$ sudo systemctl enable --now container-fosshttpd.service
Created symlink /etc/systemd/system/default.target.wants/container-fosshttpd.service → /etc/systemd/system/container-fosshttpd.service.

Step 7: Check the status of the service (container-fosshttpd.service) to verify:

systemctl status
systemctl status container
@fedora ~]$ sudo systemctl status container-fosshttpd.service
● container-fosshttpd.service - Podman container-fosshttpd.service
Loaded: loaded (/etc/systemd/system/container-fosshttpd.service; enabled; vendor preset: disabled)
Active: activating (start) since Sat 2022-02-19 15:14:57 EAT; 3s ago
Step 8: Stop container service (container-fosshttpd.service):
# systemctl --user stop container-fosshttpd.service

Auto-starting pods using systemd

You can use the systemctl command to start multiple containers as systemctl services. A good practice is to use the systemctl command on the pod and not to start or stop containers individually.
Step 1: Create an empty pod (foss-pod):

@fedora ~]$ podman pod create --name foss-pod
b952580fdbe4b4f006f706f6ae74fbbee0cbba3d86e0f287fc1beac33013815b

List all pods to verify:

# podman pod ps
podman pod ps
podman pod ps

Step 2: Create containers in the empty pod (foss-pod):

# podman create --pod foss-pod --name container_0 docker.io/library/httpd
# podman create --pod foss-pod --name container_1 docker.io/library/httpd

List all pods and containers to verify:

$ podman ps -a –pod
podman create pod
podman create pod

Step 3: Generate the systemd unit file for the new pod:

$ podman generate systemd --files --name foss-pod
@fedora ~]$ podman generate systemd --files --name foss-pod
/home/user/pod-foss-pod.service
/home/user/container-container_0.service
/home/user/container-container_1.service

Note: Three systemd unit files are generated for the foss-pod pod and the containers (container_0, container_1).

Step 4: View the content of the pod-foss-pod.service unit file:

# cat pod-foss-pod.service
systemd pod service
systemd pod service (pod-foss-pod.service)

Step 5: View the content of container service (container-container_0.service, container-container_1.service) unit files:

# cat container-container_0.service
# cat container-container_1.service
systemd container service
systemd container service (container-container_0.service)

Step 6: Copy all the generated files to $HOME/.config/systemd/user:

# cp pod-foss-pod.service container-container_0.service container-container_1.service $HOME/.config/systemd/user

Step 7: Enable the service to start at user login:

# systemctl enable --user pod-foss-pod.service
Created symlink /home/user1/.config/systemd/user/multi-user.target.wants/ppod-foss-pod.service → /home/user1/.config/systemd/user/pod-foss-pod.service.
Created symlink /home/user1/.config/systemd/user/default.target.wants/pod-foss-pod.service → /home/user1/.config/systemd/user/pod-foss-pod.service

Check if the service (pod-foss-pod.service) is enabled:

$ systemctl is-enabled pod-foss-pod.service
enabled

Auto-updating containers using Podman

To auto-update containers with Podman, you need to install the container-tools module. You can use the podman auto-update command to automatically update containers. The command updates services when the image is updated on the registry. To use auto-updates, you have to create a container with the –label “io.containers.autoupdate=image” label and run it in a systemd unit generated by podman generate systemd –new command.

Podman searches for running containers with the “io.containers.autoupdate” label set to “image” and communicates to the container registry. If the image has changed, the container, dependencies, and environment are restarted.

Step 1: Start a container (httpd):

@fedora ~]$ podman run --label "io.containers.autoupdate=image" --name foss-httpd-0 -dt docker.io/library/httpd
57ddf10eedb2f6779360b15554da191f8d217bfbaca634cd1a92833d1c21e332

Step 2: Generate a systemd unit file for the foss-httpd-0 container:

@fedora ~]$ podman generate systemd --new --files --name foss-httpd-0
/home/user/container-foss-httpd-0.service

Step 3:Copy unit files to /usr/lib/systemd/system for installing it as a root:

# cp -Z ~/container-foss-httpd-0.service /usr/lib/systemd/system

Step 4: Reload systemd manager configuration:

# systemctl daemon-reload

Step 5: Start and check the status the container (foss-httpd-0):

# systemctl start container-foss-httpd-0.service
# systemctl status container-foss-httpd-0.service

Step 5: Auto-update the container:

# podman auto-update

Auto-updating containers using systemd

You can also auto-update the containers using the pre-installed podman-auto-update.timer and podman-auto-update.service systemd service. You can configure the podman-auto-update.timer to trigger auto-updates at a specific time or date. The podman-auto-update.service can also be started by the systemctl command, or you can use it as a dependency by other systemd services. In essence, you can trigger auto-updates based on events and time in various ways to meet your use case and needs.
You need to install the container-tools module to continue with the next steps.

Step 1: Display and view the podman-auto-update.service unit file:

# cat /usr/lib/systemd/system/podman-auto-update.service
[Unit]
Description=Podman auto-update service
Documentation=man:podman-auto-update(1)
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/podman auto-update
ExecStartPost=/usr/bin/podman image prune -f
[Install]
WantedBy=default.target

Step 2: Display and view the podman-auto-update.timer unit file:

@fedora ~]$ cat /usr/lib/systemd/system/podman-auto-update.timer
[Unit]
Description=Podman auto-update timer
[Timer]
OnCalendar=daily
RandomizedDelaySec=900
Persistent=true
[Install]
WantedBy=timers.target

Notes:

  • OnCalendar=daily – The podman auto-update command is triggered daily at midnight.

Step 3: Enable the podman-auto-update.timer service at system boot:

# systemctl enable podman-auto-update.timer

Step 4: Start the systemd service (podman-auto-update.service):

# systemctl start podman-auto-update.timer

Step 5: Verify by listing all your system timers:

# systemctl list-timers --all
NEXT                        LEFT   LAST PASSED  UNIT                    ACTIVATES
TUE 2022-02-22 00:00:00 EAT 9h left n/a n/a    podman-auto-update.timer podman-auto-update.service

Notes:

  • The podman-auto-update.timer activates the podman-auto-update.service.

Additional documentation

Wrapping up

Containers function just like processes running on your local system, without configuring a virtual machine or an emulated environment. On the other hand, systemd is a versatile tool for managing services and dependencies in Linux systems.

The article, though on the longer side, is a guide to managing containers as a systemd service with the podman tool. You will get examples of running and managing containers using the Podman and systemd services. Once you configure systemd and Podman in your system, it becomes relatively easy to manage dependencies, start, stop, and auto-update containers and pods.

AD

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

SPONSOR AD
22,858FansLike
451FollowersFollow
16SubscribersSubscribe

More Articles Like This