Among its catalog of Universal Base Images (UBI), Red Hat provides a kind / flavor prefixed
ubi8-initimages contains the
systemdinitialization system, making them useful for building images in which you want to run
systemdservices, such as a web server or file server. […]
Cmdis set to
/sbin/init, instead of
bash, to start the
systemdInit service by default. It includes
processrelated commands (
ubi8does not. […]
ubi8-initignores normal signals to exit (
SIGKILL), but will terminate if it receives
The point seems to be—quick disclaimer: I'm not a specialist at all of this topic, just curious—that different communities have different opinions:
Upstream docker says any process can run as
PID 1in a container. And they have proven this by the thousands of docker-formatted container images that are present on their container image registry.
The systemd developers believe the opposite. They say you should always run an init system as
PID 1in any environment.
They state that
PID 1provides services to the processes inside the container that are part of the Linux API. […]
People building docker-formatted images have to build their own Init command for launching the container. They can’t simply use the systemd unit file just the way that the OS and packager intends. This is also part of the Linux Service API.
$ docker run --name ubi-init -d --rm registry.access.redhat.com/ubi8/ubi-init # Init is running as the PID 1 $ docker exec -it ubi-init ps -eaf # UID PID PPID C STIME TTY TIME CMD # root 1 0 0 08:09 ? 00:00:00 /sbin/init # However it does not work $ docker exec -it ubi-init systemctl --type=service # System has not been booted with systemd as init system (PID 1). Can't operate. # Failed to connect to bus: Host is down
systemd expects a certain number of things, see Running systemd in a non-privileged container for the detail. A simple way to make it work is to run docker in privileged mode.
When the operator executes docker run –privileged, Docker will enable access to all devices on the host as well as set some configuration in AppArmor or SELinux to allow the container nearly all the same access to the host as processes running outside containers on the host. — Docker run reference
So let's try by installing and running an Apache HTTP server.
# Run and expose the port 80 docker run --privileged --name ubi-init -p 80:80 -d --rm registry.access.redhat.com/ubi8/ubi-init # Installation docker exec ubi-init dnf install -y httpd # Start docker exec ubi-init systemctl start httpd # Checking if it runs docker exec ubi-init systemctl status httpd # ● httpd.service - The Apache HTTP Server # Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled) # Active: active (running) since Sun 2020-01-19 10:42:52 UTC; 5s ago
Now the Apache start page should be displayed in your preferred web browser at http://localhost.
From a docker image
By defining a simple docker image for that the advantage in terms of simplicity and standardisation are obvious.
FROM registry.access.redhat.com/ubi8/ubi-init # Install httpd RUN dnf -y install httpd && \ dnf clean all && \ # Tell systemd to start httpd systemctl enable httpd # Expose its default port EXPOSE 80
# Build the image $ docker build --rm --pull -t httpd-init . # Run it $ docker run --privileged --name httpd-init -d --rm -p 80:80 httpd-init
We can check that the logs are written in the journal.
# Check that logs are written in the journal $ docker exec httpd-init journalctl -u httpd # Jan 19 10:46:38 96829b67cf16 systemd: Starting The Apache HTTP Server... # Jan 19 10:46:38 96829b67cf16 httpd: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress # this message # Jan 19 10:46:38 96829b67cf16 systemd: Started The Apache HTTP Server. # Jan 19 10:46:38 96829b67cf16 httpd: Server configured, listening on: port 80 # But nothing in docker logs ... $ docker logs httpd-init
What is the problem?
The main one is that
journaldcontrols the output of containers, whereas tools like Kubernetes and OpenShift expect the containers to log directly to
stderr. So, if you are going to manage your containers via Orchestrator like these, then you should think twice about using systemd-based containers. Additionally, the upstream community of Docker and Moby were often hostile to the use of
systemdin a container.