1
votes

We currently have a number of different services running on a host, and we are using systemd extensively, including systemd-notify for message passing and an own front-end for service management.

We would like to start running these services inside a container, to simplify dependency management and running multiple versions alongside each-other for testing. We want:

  • systemd-notify
  • Logging to both systemd journal and syslog
  • Start and stop services with systemctl start / stop.

Please note; Most questions are about running systemd inside a docker container. That is not what this question is about. Instead, I want to run a (docker?) container inside systemd.

1

1 Answers

2
votes

We went with the following solution:

Podman

We decided to go with Podman. Podman is a wrapper around RunC, with the CLI tools tuned to be a drop-in replacement for Docker. However, because it's not running the containers under a daemon (which I like a bit better anyway), hardly any plumbing is required to make systemd-notify work.

Just specifying Environment=NOTIFY_SOCKET=/run/systemd/notify in the sytemd service file suffices.

See here as well.

systemd-notify

Full example:

I'm using the systemd-notify test-script from: https://github.com/bb4242/sdnotify

Dockerfile

FROM python

COPY test.py /

RUN pip install sdnotify
RUN chmod 755 /test.py

ENTRYPOINT ["/usr/local/bin/python", "test.py"]
CMD ["run"]

EXPOSE 8080

build.sh - Creates the Podman container, needs to be in the same folder as Dockerfile and test.py script.

#!/bin/bash
IMAGE_NAME=python-test
CONTAINER_NAME=python-test
sudo podman build . -t ${IMAGE_NAME}
sudo podman rm ${CONTAINER_NAME}
sudo podman create -e PYTHONUNBUFFERED=true -d --name=${CONTAINER_NAME} ${IMAGE_NAME}

notify-test.service

[Unit]
Description=A test service written in Python

[Service]
# Note: setting PYTHONUNBUFFERED is necessary to see the output of this service in the journal
# See https://docs.python.org/2/using/cmdline.html#envvar-PYTHONUNBUFFERED
Environment=PYTHONUNBUFFERED=true
Environment=NOTIFY_SOCKET=/run/systemd/notify
SyslogIdentifier=notify-test
NotifyAccess=all

ExecStart=/usr/bin/podman start -a python-test
ExecStop=/usr/bin/podman stop python-test

# Note that we use Type=notify here since test.py will send "READY=1"
# when it's finished starting up
Type=notify

[Install]
WantedBy=multi-user.target

So first install podman, and put the test.py from the url above, Dockerfile, and build.sh in a separate folder. Run ./build.sh.

Then take the .service file, and put it with other systemd service files in /usr/lib/systemd/user. Do sudo systemctl daemon-reload.

Now, the service can be started and stopped with sudo systemctl start notify-test and sudo systemctl stop notify-test.

Logging

systemd will by default automatically log whatever is written to stdout/stderr to both its own journal (accessible with journalctl), and to the syslog.

See: https://www.freedesktop.org/software/systemd/man/systemd.exec.html

SyslogLevelPrefix= Takes a boolean argument. If true and StandardOutput= or StandardError= are set to journal or kmsg (or to the same settings in combination with +console), log lines written by the executed process that are prefixed with a log level will be processed with this log level set but the prefix removed. If set to false, the interpretation of these prefixes is disabled and the logged lines are passed on as-is. This only applies to log messages written to stdout or stderr. For details about this prefixing see sd-daemon(3). Defaults to true.

Two issues:

Problem: When using podman as ExecStart=, the log-source will by default be the name of the executable, which is 'podman'.

Solution: Use the SyslogIdentifier= to specify the name for logging, like in the .service file example above.

Problem: There won't be any difference between log-levels for log-lines.

Solution: Like described here in the systemd documentation, prepend the log-lines with <7> (for debug), <6> (for info), <4> (for warn) etc. to have systemd set the right log levels everywhere, including for syslog. Even get colors in the journalctl tool for free!