docker - 如何在 systemd 中运行在容器中运行的服务,包括 systemd-notify 和日志记录

标签 docker containers systemd

我们目前在一台主机上运行着许多不同的服务,我们正在广泛使用 systemd,包括用于消息传递的 systemd-notify 和用于服务管理的自己的前端。

我们希望开始在容器内运行这些服务,以简化依赖管理并同时运行多个版本进行测试。我们想要:

  • 系统通知
  • 记录到 systemd 日志和系统日志
  • 使用 systemctl start/stop 启动和停止服务。

请注意;大多数问题都是关于在 docker 容器中运行 systemd 的。这不是这个问题的意思。相反,我想在 systemd 中运行一个(docker?)容器。

最佳答案

我们采用了以下解决方案:

播客

我们决定使用 Podman . Podman 是 RunC 的包装器,其 CLI 工具已调整为 Docker 的直接替代品。然而,因为它不是在守护进程下运行容器(无论如何我更喜欢它),所以几乎不需要任何管道来使 systemd-notify 工作。

只需在 sytemd 服务文件中指定 Environment=NOTIFY_SOCKET=/run/systemd/notify 即可。

参见 here

系统通知

完整示例:

我正在使用来自:https://github.com/bb4242/sdnotify 的 systemd-notify 测试脚本

docker 文件

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 - 创建 Podman 容器,需要与 Dockerfile 和 test.py 脚本位于同一文件夹中。

#!/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}

通知测试服务

[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

所以首先安装podman,将上面url中的test.py、Dockerfile、build.sh放在单独的文件夹中。运行 ./build.sh

然后获取.service 文件,并将其与其他systemd 服务文件放在/usr/lib/systemd/user 中。执行 sudo systemctl daemon-reload

现在,可以使用 sudo systemctl start notify-testsudo systemctl stop notify-test 启动和停止服务。

记录

systemd 默认情况下会自动将写入 stdout/stderr 的任何内容记录到它自己的日志(可通过 journalctl 访问)和系统日志。

参见: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.

两个问题:

问题:当使用 podman 作为 ExecStart= 时,日志源默认为可执行文件的名称,即“podman”。

解决方案:使用 SyslogIdentifier= 指定日志记录的名称,如上面的 .service 文件示例。

问题:日志行的日志级别之间没有任何区别。

解决方案:如所述here在 systemd 文档中,在日志行前面加上 <7>(用于调试)、<6>(用于信息)、<4>(用于警告)等,让 systemd 在任何地方设置正确的日志级别,包括 syslog。甚至可以免费在 journalctl 工具中获取颜色!

关于docker - 如何在 systemd 中运行在容器中运行的服务,包括 systemd-notify 和日志记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63540832/

相关文章:

bash - 如何检查我的本地 docker 镜像是否已过时,而无需从其他地方推送?

azure - 无法在 Azure Windows 10 VM 上启动 'Docker for windows'

c# - 尝试在Docker管道中生成测试覆盖率时在 “No report files specified”中运行(Linux)

c++ - std::stack<boost::shared_ptr<T>> 的深拷贝

c++ - 类型转换 shared_ptr 的容器

css - 响应式设计中的容器/图像定位

mongodb - 无法连接到 WSL2 内 docker 内的 mongo

docker - 如何更改kubernetes容器/ pods 的端口?

linux - fail2ban 正则表达式停止工作 [Debian 8 - Jessie]

docker - 厨房-Docker 和 Systemd