Integrating Podman and systemd
Perfect Harmony
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.
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
(incl. VAT)
Buy ADMIN Magazine
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Most Popular
Support Our Work
ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.