请教一个 docker+systemd 的问题
在 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 来管理, 自动重启什么的就行.
我说几点:
- 首先,Docker 是应用容器( Application Container ),应用容器的设计理念就是「一个容器 = 一个应用主进程」。如果你需要在容器里塞很多平行的进程,那么已经在逆设计理念硬用了。等于是反天道而行,有问题是自然的。所以要么 (1) 拆分应用成多容器,用 TCP 交流;(2) 换成系统容器( System Container ),比如 LXD ;
抛开第一点不谈,如果你只是要编排任务,也不应该让本来用来管理系统资源和内核的 systemd 硬上(虽然它确实有编排服务的功能,但它还有很多别的职能啊),你需要的是「 systemctl 独立绿色版」,我推荐 Supervisord: supervisord.org/ 。
#4 补充一下:
- 既然楼主没说清楚为什么要用 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 权限有关?
- Dockerfile entrypoint PID 1 需要是 systemd 或者 init
/sbin/init -> /lib/systemd/systemd
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 ,可以检查一下
arm 构架的怎么破 x86 的看 nasyun 的老帖子能搞定 太小众了,虽然群晖有的功能威联通基本都有,但就是不好用。 还是推荐买个 X86 折腾吧。 非要 Ar…
服务器在客户厂里, 客户没有机房, 就放在厂子机器旁边. 每天下班后, 客户员工从来不会去关闭电脑, 都是直接拉闸整厂断电. 系统稳定运行了大半年后, 从最近开始, 每隔几个月…
非常开心。自从几年前,我在 V2EX 发帖获得灵感发布 cool 之后,这是第二个个人捐助来感谢我对开源所做出的贡献的。连夜把两位记录在了我的网站上。第一笔是来自支付宝,我不好…