在 docker 镜像中增加了 systemd 的功能,一直没啥问题,最近在 ubuntu 22.04 LTS 中出现了问题,
在 docker 容器中运行 systemctl ,显示Failed to get D-Bus connection: No such file or directory,而在 ubuntu 20.0 4LTS 中就正常。镜像系统是 centos 7.9.
不知道该从哪入手去找原因,哪位有相关的经验提示一下。现在只能想办法把 systemctl 去掉,但是这个成本比较高。

我解释一下,因为这产品最初是在虚拟机里跑的,它的升级方式用到了 systemctl restart service, 而且前端的升级是利用后端的服务实现的,这个容器中不但用到了 systemctl ,还有多个服务在跑(tomcat/nginx)。现在在进行重构,分离服务,去掉对 systemd 的依赖,但是因为涉及到系统的升级,没那么快。
至于在容器中跑 systemd ,hub.docker.com 就有现成的,只不过用的确实不多。
我现在主要的问题是,ubuntu 升了个版本就出问题了,按道理说 docker 应该跟宿主机的系统没关系才对。

我只能建议你把问题描述丢给 deepseek R1

遇到技术问题就去问 AI 。论坛是吹牛逼的地方,你想把论坛当 AI 用?

镜像中增加 systemd 听上去有点奇怪啊, 作用是什么? "Failed to get D-Bus connection: No such file or directory" 看上去像是 systemctl 跟 systemd daemon 之类的东西无法通信. 容器内一般不用进程管理器了, 一个进程一个容器由外面的 docker 来管理, 自动重启什么的就行.

我说几点:

  1. 首先,Docker 是应用容器( Application Container ),应用容器的设计理念就是「一个容器 = 一个应用主进程」。如果你需要在容器里塞很多平行的进程,那么已经在逆设计理念硬用了。等于是反天道而行,有问题是自然的。所以要么 (1) 拆分应用成多容器,用 TCP 交流;(2) 换成系统容器( System Container ),比如 LXD ;
  2. 抛开第一点不谈,如果你只是要编排任务,也不应该让本来用来管理系统资源和内核的 systemd 硬上(虽然它确实有编排服务的功能,但它还有很多别的职能啊),你需要的是「 systemctl 独立绿色版」,我推荐 Supervisord: supervisord.org/ 。

    #4 补充一下:

  3. 既然楼主没说清楚为什么要用 systemctl ,我再预判一下楼主的实际问题:是不是有应用文档里只教了怎么用 systemctl 启动,所以离了 systemctl 就不知道怎么启了?

如果是这样,我建议仔细学一下 systemd.service 的工作方式,去掉这东西的成本可能没你想得那么高。

请教一下,如果是 dev container 的话,一个 dev container 同时启动后端服务与 PostgreSQL 如何?还是说依然需要用 docker compose 的形式?

如果非要多个服务塞同一个容器,不要用很依赖系统的 systemd ,用 openrc 或 supervisor

#6 生产和开发是不一样的,因为不用考虑服务启停状态这些东西,dev container 里你怎么折腾都可以,怎么方便怎么来。上面说的这些只适用于生产部署。

把数据库和 app 都装进一个容器里当然可以,你试试就知道了,不要照本宣科。

没太看懂楼主的问题,如果容器的基础镜像用的是 ubuntu ,那默认就是 systemd 在管理进程啊,当然 init.d 也能用。
另外 centos 7.9 也是用的 systemd 吧?没记错的话

就先检查是不是真的拉起来了 systemd ,以及 dbus.socket/service 有没有跑起来(文件位置和进程)

systemd 默认在容器里跑不了啊,再说了 systemd 这么臃肿的玩意儿就不是在容器里用的

其实能跑,只是容器运行时要给点额外的处理(挂载一些需要的文件系统),容器管理器可能自动做了这些事情
比如 podman 的 docs.podman.io/en/v5.1.1/markdown/podman-run.1.html#systemd-true-false-always
甚至还有 registry.access.redhat.com/ubi9-init:latest 这种镜像就用来跑 systemd

不过我的电脑上 centos7 的容器是跑不了的,因为老的 systemd 要求 cgroupv1...

与 root 权限有关?

  1. Dockerfile entrypoint PID 1 需要是 systemd 或者 init

/sbin/init -> /lib/systemd/systemd

  1. Host 如果是 cgroupv1 可以 bind mount -v /sys/fs/cgroup:/sys/fs/cgroup 如果是 v2 的话要 --cap-add SYS_ADMIN, 然后 systemd 会自己 mount cgroup fs, sample
    docker run -d --name test1 --tmpfs /run --tmpfs /tmp --cap-add SYS_ADMIN image

    很早之前这么跑过, 要挂一堆 hostfs 进去, 上面已经有人给了参考链接, 另外镜像也要装很多东西, 而且 systemd 很多包的安装脚本没考虑在容器里面, 安装时候也有不小的问题, 总之一句话, 能跑但不建议, 会有奇奇怪怪的问题, 尤其是版本升级之类的时候, 如果是跑单进程, 建议找个 dockerfile 参考一下在容器里面怎么跑, 如果是多进程, 优先考虑 compose 之类的多容器方案, 其次是单容器多进程的 tinit/supervisor 这种方案

    放 systemd 进去根本不是最佳实践,必须去掉

    Docker 直接 entrypoint 运行就是,套 systemd 是个傻情况?

    之前遇到一次这种情况是 CentOS user ,用 root 才行,的确是 DBus socket 连不上

    #10 没拉起来,拉起来后会有一个/usr/lib/systemd/systemd-journald 进程,我尝试手动运行,没反应。github 上有个 python 版的 systemctl ,我准备替换一下试试。

    容器的 entrypoint 得是 systemd ,可以检查一下