First Look at the UBI Init Base Images
Among its catalog of Universal Base Images (UBI), Red Hat provides a kind / flavor prefixed init
.
The UBI
ubi8-init
images contains thesystemd
initialization system, making them useful for building images in which you want to runsystemd
services, such as a web server or file server. […]
Inubi8-init
, theCmd
is set to/sbin/init
, instead ofbash
, to start thesystemd
Init service by default. It includesps
andprocess
related commands (procps-ng
package), whichubi8
does not. […]
Also,ubi8-init
setsSIGRTMIN+3
as theStopSignal
, assystemd
inubi8-init
ignores normal signals to exit (SIGTERM
andSIGKILL
), but will terminate if it receivesSIGRTMIN+3
.
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
Upstream docker says any process can run as
PID 1
in a container. And they have proven this by the thousands of docker-formatted container images that are present on their container image registry.
Systemd developers
The systemd developers believe the opposite. They say you should always run an init system as
PID 1
in any environment.
They state thatPID 1
provides 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.
First try
$ 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
Privileged mode
To run 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
Quick exploration
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[1]: Starting The Apache HTTP Server...
# Jan 19 10:46:38 96829b67cf16 httpd[28]: 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[1]: Started The Apache HTTP Server.
# Jan 19 10:46:38 96829b67cf16 httpd[28]: Server configured, listening on: port 80
# But nothing in docker logs ...
$ docker logs httpd-init
What is the problem?
The main one is that
systemd
/journald
controls the output of containers, whereas tools like Kubernetes and OpenShift expect the containers to log directly tostdout
andstderr
. 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 ofsystemd
in a container.
Next
To go further it could be interesting to have a look at Podman.
This article explains how and the advantages of using this setup.
I may give it a try in a next article…