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 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
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.
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.
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.