Photo by Nick Fewings on Unsplash

Photo by Nick Fewings on Unsplash

Integrating Podman and systemd

Perfect Harmony

Article from ADMIN 62/2021
By
With the integration of Podman and systemd, you can put any software inside a container under the control of systemd and see almost no difference between running the service directly on the host or inside a container.

Podman is considered the standard when it comes to managing containers and pods. Seamless integration into the systemd world is a big help, especially in environments where Kubernetes is not used and users want to deploy arbitrary software within containers. After the release of Podman version 2.0, the two components now work in even closer collaboration.

Some readers might frown at the thought of linking Podman [1] and systemd [2] more closely, and with good reason. After all, microservices should run primarily within containers, without the need for a service manager like systemd. This idea is correct as far as it goes, and in an ideal world, Kubernetes exclusively manages orchestration for containers with microservices. However, experience shows that this is not always possible and that other architectures must also be taken into account. One reason is certainly that software often still exists in classic form and does not necessarily follow a microservice-based architecture.

Administrators don't want to miss out on the benefits that running software inside a container bring, and there are use cases for running software in containers like regular services on a host. Because Podman is known to be based on a fork/exec model, unlike Docker, it is easy to put containers under the control of systemd to leverage all of the benefits that the system and service manager offers. In this article, I show examples of both use cases.

Inside and Outside Containers

To begin, you will discover how easy it is to put any software inside a container under the control of systemd. Listing 1 shows a container file that you can use to create a new container image. The description file for the new image installs the desired software (just the Apache web server in this case), creates a simple configuration for the service, and creates a systemd unit file. Finally, instructions follow for starting the systemd-init service inside containers based on this image. With

podman build -t myhttpd -f <containerfile>

Listing 1

Container File

FROM fedora:latest
RUN dnf -y install httpd psmsic ; yum clean all; systemctl enable httpd;
RUN echo "Hello administrator" > /var/www/html/index.html
RUN mkdir /etc/systemd/system/httpd.service.d/; echo -e '[Service]\nRestart=always' > /etc/systemd/system/httpd.service.d/httpd.conf
EXPOSE 80
CMD [ "/sbin/init" ]

you create a new image based on the container file, which is then used directly afterward to start a new container with the command:

podman run -d --name=myhttpd -p 8080:80 myhttpd

If you call the Podman command as a non-root user, this method basically works because Podman supports rootless containers, but you cannot bind the container service to a privileged host port (<=1024) in this case. Instead, container port 80 is mapped to host port 8080 with the -p 8080:80 option. Finally, the following test confirms that the web server started correctly inside the container and is now accessible from the host on port 8080:

curl --silent http://localhost:8080
Hello administrator

If you call the pstree command inside the container, you will see that the httpd process (Listing 2) is now under the control of systemd. Of course, you can also launch other software in the same way using systemd inside a container. Depending on the software used, the unit file may be somewhat larger, which is why it is a good idea in such a case to copy the file from the host system to the container,

COPY httpd.conf /etc/system/system/httpd.service.d/

as shown here with the COPY command within the container file.

Listing 2

Systemd Control of Httpd Process

podman exec myhttpd /usr/bin/pstree
systemd-+-dbus-broker-lau---dbus-broker
        |-httpd-+-httpd
        |       |-2*[httpd---64*[{httpd}]]
        |       `-httpd---80*[{httpd}]
        |-systemd-homed
        |-systemd-journal
        `-systemd-logind

Create systemd Configuration with Podman

Conversely, you can also tell Podman to create a systemd unit file for a service and then use it to manage containers like regular services on the host system. For example, you can start and stop containers and the applications running in them with systemctl. To prevent SELinux from blocking access by a container process to the host's cgroup system, you first need to allow it with the SELinux boolean:

setsebool -P container_manage_cgroup on

If you already have a running container named apache and now want to create a systemd configuration for it, use the commands:

podman generate systemd --files --name apache
sudo cp ./container-apache.service /etc/systemd/system/

The resulting unit file (Listing 3) is first placed in the current directory and then copied to the systemd directory so that the init system has direct access to the file.

Listing 3

etc/system/system/container-apache.service

container-apache.service
autogenerated by Podman 2.0.4
[Unit]
Description=Podman container-apache.service
Documentation=man:podman-generate-systemd(1)
Wants=network.target
After=network-online.target
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
ExecStart=/usr/bin/podman start apache
ExecStop=/usr/bin/podman stop -t 10 apache
ExecStopPost=/usr/bin/podman stop -t 10 apache
PIDFile=/var/run/containers/storage/overlay-containers/0b43a756b2eb9947239827e571675cef10095515be02a05d7318ba8701e819ff/userdata/conmon.pid
KillMode=none
Type=forking
[Install]
WantedBy=multi-user.target default.target

Figure 1 shows how you now use systemctl enable to activate the new container service. The call to curl finally confirms that the container has been started and the web server is running in the container. If you restart the computer, systemd will also take care of activating the new container service from now on.

Figure 1: The systemctl enable command enables the container service.

Another useful feature is that you can now create portable systemd unit files that can be used on other machines to start containers with systemd. To do this, simply add the --new option when calling podman. The unit file created in this way can then be used on the local computer or on other computers to place the desired container under systemd control with the command:

podman generate systemd --files --new --name apache

If the image file for the container does not yet exist locally, the registry downloads it as soon as systemd starts the container.

Update Container Images with Podman

Podman now has an auto-update feature for images. If you use the option --label io.containers.autoupdate=image when starting a new container, you can use the podman auto-update command to make Podman first check whether a new image exists for this container in the registry before starting a container. If so, it will download it, tell systemd to stop the running container, and then start a new container based on the new image. Note that this feature is only available for containers that are under systemd control.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

comments powered by Disqus