Podman - systemd in containers

Podman provides application containers in a daemonless way. Very often, one needs a single application in a container. But what about multiple applications or development scenarios, where some kind of init service is needed?

Podman - systemd in containers

Podman provides application containers in a daemonless way. Very often, one needs a single application in a container. But what about multiple applications or development scenarios, where some kind of init service is needed? Podman is prepared for these scenarios and this article will explain how to work with system in containers.

If you just started with Podman containers, you should have a look at the Getting Started and Images article, first.

What is systemd?

Answering the question: "What is systemd?" is not as easy, as one might think. Very often it is reduced to "an init daemon". The project itself describes systemd this way:

"systemd is a suite of basic building blocks for a Linux system. It provides a system and service manager that runs as PID 1 and starts the rest of the system."

Why systemd in containers?

Very often, one will have a single application in a container. Running a httpd container will only have Apache httpd running in it and a MariaDB container will have only MariaDB in it.

Sometimes it is useful to have multiple applications in a container or interact with systemd directly. Ansible Development for example profits from containers with systemd in it, since you can test the service module.

You might also want to have multiple applications running in a container to test a certain setup or have your application bundled in a single container. A good example for something like this will be to have nginx + php-fpm + MariaDB together. Otherwise, you will need 3 containers, which is not as convenient for a quick test.

Podman configuration

Hint
The guide is tested on Fedora 33 with Podman 3.0.1.

Podman has some sane defaults to run containers, that use systemd internally. Docker for example needs some special privileges and mount options to use systemd in containers. This is not needed in Podman. The man page (man podman-run) states:

--systemd=true|false|always
Run container in systemd mode. The default is true.

The value true indicates, that Podman detects if systemd is running in the container and will do the heavy lifting for you. This means, Podman will set up tmpfs mount points for some directories and set the stop signal to SIGRTMIN+3. In case you want to learn more about volumes and mounts, you should have a look at this or this article.

In case you want to use SELinux on the host (default for Fedora, CentOS, RedHat, etc.), you will need to allow writing to the cgroup file system.

# Allow containers to write to cgroups
$ sudo setsebool -P container_manage_cgroup true

Fedora example

Let's deploy a Fedora container with systemd on a Fedora host. In addition, we will also install nginx, php-fpm and MariaDB (since it was my example above, it might be nice to actually show it).

For this, we have to create an image. I already addressed the basics of Image building in the article "Podman - Images", if you want to have a look.

We will start with a new project directory.

# Create directory
$ mkdir fedora-web
$ cd fedora-web

# Create a Dockerfile
$ touch Dockerfile

Now, we need to edit the Dockerfile and fill in the below content.

# Use Fedora 33 as base image
FROM registry.fedoraproject.org/fedora:33

# Install systemd mariadb nginx php-fpm
RUN dnf install -y systemd mariadb-server nginx php-fpm && \
    dnf clean all

# Enable the services
RUN systemctl enable mariadb.service && \
    systemctl enable php-fpm.service && \
    systemctl enable nginx.service

EXPOSE 80

# Use systemd as command
CMD [ "/usr/sbin/init" ]
Dockerfile

Building this Dockerfile as an image is quite easy, too.

# Build image (this can take a minute or two)
$ podman image build --rm -t localhost/fedora-web:latest .

# List images
$ podman image ls
podman image ls
REPOSITORY                                     TAG              IMAGE ID      CREATED         SIZE
localhost/fedora-web                           latest           9242f607ebfd  7 minutes ago   478 MB

Finally, we can run a container from the image and check, if everything is ok.

# Run a container
$ podman container run -d \
  --name fedora-web01 localhost/fedora-web:latest

# Check running containers
$ podman container ls
CONTAINER ID  IMAGE                        COMMAND         CREATED         STATUS             PORTS   NAMES
d3a6e81d0393  localhost/fedora-web:latest  /usr/sbin/init  18 seconds ago  Up 18 seconds ago          fedora-web01

# Check processes in the container
$ podman container top fedora-web01 
USER              PID   PPID   %CPU    ELAPSED           TTY   TIME   COMMAND
...
root              1     0      0.000   1m14.249008435s   ?     0s     /usr/sbin/init 
...
apache            53    23     0.000   1m13.249498961s   ?     0s     php-fpm: pool www               
...
root              66    1      0.000   1m13.249708653s   ?     0s     nginx: master process /usr/sbin/nginx 
nginx             68    66     0.000   1m13.249750573s   ?     0s     nginx: worker process 
...
mysql             164   1      0.000   1m10.250082552s   ?     0s     /usr/libexec/mysqld --basedir=/usr

As you can see, there are processes running for php-fpm, MySQL (MariaDB) and nginx. I have removed some lines of the output for better readability.

That's basically it. Everything you need to do now, is to configure each of these services and put your code in the container.

Documentation

In case you want to dig into this topic a bit more, here you go. Be aware, that using systemd in a container is still considered an "edge case" and you may not find a ton of documentation for it.

NAME — Podman documentation
How to run systemd in a container - Red Hat Developer
In this article, we show how and why to run systemd in a container using Podman.

Conclusion

Podman can run systemd in a container quite well. This can be handy for shipping complete application stacks as one container or for development and testing purposes. Podman also makes it much easier to work with systemd enabled containers as Docker, even in rootless mode.

Podman has even more up its sleeve with regard to systemd and I will address "Podman - Managed via systemd" in another article.