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

请教一个 docker+systemd 的问题

  •  
  •   catamaran · 33 天前 · 2143 次点击
    这是一个创建于 33 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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


    没太看懂楼主的问题,如果容器的基础镜像用的是 ubuntu ,那默认就是 systemd 在管理进程啊,当然 init.d 也能用。
    另外 centos 7.9 也是用的 systemd 吧?没记错的话
    yanqiyu
        10
    yanqiyu  
       33 天前
    就先检查是不是真的拉起来了 systemd ,以及 dbus.socket/service 有没有跑起来(文件位置和进程)
    Nitroethane
        11
    Nitroethane  
       33 天前
    systemd 默认在容器里跑不了啊,再说了 systemd 这么臃肿的玩意儿就不是在容器里用的
    yanqiyu
        12
    yanqiyu  
       33 天前
    @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  
       33 天前
    与 root 权限有关?
    feedcode
        14
    feedcode  
       33 天前
    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  
       33 天前
    很早之前这么跑过, 要挂一堆 hostfs 进去, 上面已经有人给了参考链接, 另外镜像也要装很多东西, 而且 systemd 很多包的安装脚本没考虑在容器里面, 安装时候也有不小的问题, 总之一句话, 能跑但不建议, 会有奇奇怪怪的问题, 尤其是版本升级之类的时候, 如果是跑单进程, 建议找个 dockerfile 参考一下在容器里面怎么跑, 如果是多进程, 优先考虑 compose 之类的多容器方案, 其次是单容器多进程的 tinit/supervisor 这种方案
    defunct9
        16
    defunct9  
       33 天前 via iPhone
    放 systemd 进去根本不是最佳实践,必须去掉
    Ipsum
        17
    Ipsum  
       33 天前
    Docker 直接 entrypoint 运行就是,套 systemd 是个傻情况?
    palytoxin
        18
    palytoxin  
       32 天前
    之前遇到一次这种情况是 CentOS user ,用 root 才行,的确是 DBus socket 连不上
    catamaran
        19
    catamaran  
    OP
       32 天前
    @yanqiyu #10 没拉起来,拉起来后会有一个/usr/lib/systemd/systemd-journald 进程,我尝试手动运行,没反应。github 上有个 python 版的 systemctl ,我准备替换一下试试。
    yanqiyu
        20
    yanqiyu  
       32 天前
    @catamaran 容器的 entrypoint 得是 systemd ,可以检查一下
    julyclyde
        21
    julyclyde  
       32 天前
    理论上不应该“一直没啥问题”的啊

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