V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
catamaran
V2EX  ›  Linux

请教一个 docker+systemd 的问题

  •  
  •   catamaran · 2 天前 · 1406 次点击

    在 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 去掉,但是这个成本比较高。

    第 1 条附言  ·  1 天前
    我解释一下,因为这产品最初是在虚拟机里跑的,它的升级方式用到了 systemctl restart service, 而且前端的升级是利用后端的服务实现的,这个容器中不但用到了 systemctl ,还有多个服务在跑(tomcat/nginx)。现在在进行重构,分离服务,去掉对 systemd 的依赖,但是因为涉及到系统的升级,没那么快。
    至于在容器中跑 systemd ,hub.docker.com 就有现成的,只不过用的确实不多。
    我现在主要的问题是,ubuntu 升了个版本就出问题了,按道理说 docker 应该跟宿主机的系统没关系才对。
    25 条回复    2025-02-21 13:30:56 +08:00
    vincentWdp
        1
    vincentWdp  
       2 天前
    我只能建议你把问题描述丢给 deepseek R1
    Chaidu
        2
    Chaidu  
       2 天前   ❤️ 2
    遇到技术问题就去问 AI 。论坛是吹牛逼的地方,你想把论坛当 AI 用?
    snowfuck
        3
    snowfuck  
       1 天前
    镜像中增加 systemd 听上去有点奇怪啊, 作用是什么? "Failed to get D-Bus connection: No such file or directory" 看上去像是 systemctl 跟 systemd daemon 之类的东西无法通信. 容器内一般不用进程管理器了, 一个进程一个容器由外面的 docker 来管理, 自动重启什么的就行.
    w568w
        4
    w568w  
       1 天前   ❤️ 1
    我说几点:

    1. 首先,Docker 是应用容器( Application Container ),应用容器的设计理念就是「一个容器 = 一个应用主进程」。如果你需要在容器里塞很多平行的进程,那么已经在逆设计理念硬用了。等于是反天道而行,有问题是自然的。所以要么 (1) 拆分应用成多容器,用 TCP 交流;(2) 换成系统容器( System Container ),比如 LXD ;

    2. 抛开第一点不谈,如果你只是要编排任务,也不应该让本来用来管理系统资源和内核的 systemd 硬上(虽然它确实有编排服务的功能,但它还有很多别的职能啊),你需要的是「 systemctl 独立绿色版」,我推荐 Supervisord: https://supervisord.org/
    w568w
        5
    w568w  
       1 天前
    @w568w #4 补充一下:

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

    如果是这样,我建议仔细学一下 systemd.service 的工作方式,去掉这东西的成本可能没你想得那么高。
    superhot
        6
    superhot  
       1 天前
    @w568w 请教一下,如果是 dev container 的话,一个 dev container 同时启动后端服务与 PostgreSQL 如何?还是说依然需要用 docker compose 的形式?
    sagaxu
        7
    sagaxu  
       1 天前
    如果非要多个服务塞同一个容器,不要用很依赖系统的 systemd ,用 openrc 或 supervisor
    w568w
        8
    w568w  
       1 天前
    @superhot #6 生产和开发是不一样的,因为不用考虑服务启停状态这些东西,dev container 里你怎么折腾都可以,怎么方便怎么来。上面说的这些只适用于生产部署。
    memorycancel
        9
    memorycancel  
       1 天前
    @superhot 把数据库和 app 都装进一个容器里当然可以,你试试就知道了,不要照本宣科。


    没太看懂楼主的问题,如果容器的基础镜像用的是 ubuntu ,那默认就是 systemd 在管理进程啊,当然 init.d 也能用。
    另外 centos 7.9 也是用的 systemd 吧?没记错的话
    yanqiyu
        10
    yanqiyu  
       1 天前
    就先检查是不是真的拉起来了 systemd ,以及 dbus.socket/service 有没有跑起来(文件位置和进程)
    Nitroethane
        11
    Nitroethane  
       1 天前
    systemd 默认在容器里跑不了啊,再说了 systemd 这么臃肿的玩意儿就不是在容器里用的
    yanqiyu
        12
    yanqiyu  
       1 天前
    @Nitroethane 其实能跑,只是容器运行时要给点额外的处理(挂载一些需要的文件系统),容器管理器可能自动做了这些事情
    比如 podman 的 https://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...
    zbinlin
        13
    zbinlin  
       1 天前
    与 root 权限有关?
    feedcode
        14
    feedcode  
       1 天前
    1. Dockerfile entrypoint PID 1 需要是 systemd 或者 init
    /sbin/init -> /lib/systemd/systemd

    2. 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
    my3157
        15
    my3157  
       1 天前
    很早之前这么跑过, 要挂一堆 hostfs 进去, 上面已经有人给了参考链接, 另外镜像也要装很多东西, 而且 systemd 很多包的安装脚本没考虑在容器里面, 安装时候也有不小的问题, 总之一句话, 能跑但不建议, 会有奇奇怪怪的问题, 尤其是版本升级之类的时候, 如果是跑单进程, 建议找个 dockerfile 参考一下在容器里面怎么跑, 如果是多进程, 优先考虑 compose 之类的多容器方案, 其次是单容器多进程的 tinit/supervisor 这种方案
    defunct9
        16
    defunct9  
       1 天前 via iPhone
    放 systemd 进去根本不是最佳实践,必须去掉
    Ipsum
        17
    Ipsum  
       1 天前
    Docker 直接 entrypoint 运行就是,套 systemd 是个傻情况?
    palytoxin
        18
    palytoxin  
       1 天前
    之前遇到一次这种情况是 CentOS user ,用 root 才行,的确是 DBus socket 连不上
    catamaran
        19
    catamaran  
    OP
       1 天前
    @yanqiyu #10 没拉起来,拉起来后会有一个/usr/lib/systemd/systemd-journald 进程,我尝试手动运行,没反应。github 上有个 python 版的 systemctl ,我准备替换一下试试。
    yanqiyu
        20
    yanqiyu  
       1 天前
    @catamaran 容器的 entrypoint 得是 systemd ,可以检查一下
    julyclyde
        21
    julyclyde  
       1 天前
    理论上不应该“一直没啥问题”的啊

    你看看你容器里 systemd 依赖的 dbus.service 和 dbus.socket 到底启动了没
    在前后两个环境里分别看一下
    guanzhangzhang
        22
    guanzhangzhang  
       1 天前
    你的 n 个进程不会互相之间调用 systemctl 拉起其他服务和做其他服务健康检查吧,是的话写个 shell 或者轮子把 docker.sock 挂载进去伪装成 systemctl 的输出
    Maxwellwenjie
        23
    Maxwellwenjie  
       1 天前
    我好像遇到过 Dbus 报错,不知道是不是同一个问题;是 systemctl restart service 有问题;我先把 restart 关掉了“docker update --restart no <container_id_or_name>”,然后 reboot 两遍(因为第一遍还是会调用 restart );第二遍启动后 Dbus 就不报错了;希望对你有帮助
    ruanimal
        24
    ruanimal  
       22 小时 7 分钟前
    考虑换成 lxc 试试
    catamaran
        25
    catamaran  
    OP
       7 小时 24 分钟前
    最后采用开源的一个 python 脚本替换 systemctl ,https://github.com/gdraheim/docker-systemctl-replacement 。就一个文件,直接把 systemctl 替换掉。跟之前的区别是原来服务是通过 systemd 自启的,现在必须写在 docker 的 entrypoint 中,用 systemctl start service 来启动。长期方案还是不要依赖 systemd ,一个容器只纳管一个服务。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2759 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:55 · PVG 20:55 · LAX 04:55 · JFK 07:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.