Mac M1使用Docker报错 Failed to get D-Bus connection: No such file or directory的解决方案

0x00 前言

最近在Mac上安装docker的CentOS7镜像,打算开个sshd服务,使用命令:

$ systemctl start sshd

结果在启动sshd服务的时候提示报错:

Failed to get D-Bus connection: No such file or directory

0x01 运行环境

版本
MacOS 版本 Monterey 12.0.1
芯片 M1
Docker Desktop 版本 4.15.0

0x02 问题分析

D-Bus是一种与socket类似的高效、易用的进程间通信方式.
D-Bus分为两种:system bus(系统总线),用于系统(Linux)与用户程序之间进行通信和消息的传递;session bus(会话总线),用于用户程序之间进行通信.

因为systemctl与systemd通信使用的是D-Bus,所以D-Bus报错意味着要么client有问题,要么systemd有问题。这里确认是systemd出了问题,容器中的systemd进程没有启动。

systemctl是什么?

That’s because “systemctl” talks to the systemd daemon by using the d-bus. In a container there is no systemd-daemon. Asking for a start will probably not quite do what you expect - the dev-mapping need to be a bit longer.

systemd是与cgroup融合,进行系统资源管理的程序。这里cgroup如果出现问题,就会导致systemd出现问题。

docker desktop在 4.3.0的版本release-notes【传动门】中提到:

Docker Desktop now uses cgroupv2. If you need to run systemd in a container then:
Ensure your version of systemd supports cgroupv2. It must be at least systemd 247. Consider upgrading any centos:7 images to centos:8.
Containers running systemd need the following options: --privileged --cgroupns=host -v /sys/fs/cgroup:/sys/fs/cgroup:rw.

大义是:
Docker Desktop软件从4.3.0版本开始使用cgroups v2。如果你想在容器中运行systemd:
方法1: 确保你的systemd版本支持cgroups v2,systemd最低版本为247。可以考虑直接升级centos7到centos8.
方法2: 使用如下参数在容器中运行systemd:--privileged --cgroupns=host -v /sys/fs/cgroup:/sys/fs/cgroup:rw

这里再说下cgroup是什么?

Cgroups 是 control groups 的缩写,是 Linux 内核提供的一种可以限制,记录,隔离进程组(process groups)所使用物理资源的机制。最初有 google 工程师提出,后来被整合进 Linux 的内核。因此,Cgroups 为容器实现虚拟化提供了基本保证,是构建 Docker,LXC 等一系列虚拟化管理工具的基石。

docker容器是linux基于命名空间将cpu,内存,网络等系统资源实现文件系统和进程隔离实现的。

如何对多个容器的资源使用进行限制就成了解决进程虚拟资源隔离之后的主要问题,而 Control Groups(简称 CGroups)就是能够隔离宿主机器上的物理资源,例如 CPU、内存、磁盘 I/O 和网络带宽。

Linux 的 CGroup 能够为一组进程分配资源,也就是我们在上面提到的 CPU、内存、网络带宽等资源,通过对资源的分配,CGroup 能够提供以下的几种功能:
在这里插入图片描述
在cgroups v1版本中,/sys/fs/cgroups目录下定义了cpu,memory,device等资源,新建一个cgroup分组,就是在这些资源下创建分组目录。比如docker创建一个新的容器,在cpu目录下就会出现docker文件夹,docker文件夹下有5ada8be1dadb9d66f565a1d58b214df37c630c80022e5d141282d17ab8248e97的目录,其中5ada8xxxx就是容器的hash。

sh-4.2# ls /sys/fs/cgroup/
blkio  cpu  cpu,cpuacct  cpuacct  cpuset  devices  freezer  hugetlb  memory  net_cls  net_cls,net_prio  net_prio  perf_event  pids  rdma  systemd

在这里插入图片描述
cgroup v1版本权限过大,隔离策略混乱会导致一些安全性问题,所以才有了cgroup v2版本,可以容docker在非root权限下运行docker daemon,减少了docker容器权限过大,导致逃逸等安全问题。
所以在docker desktop 4.3.0版本使用了cgroup v2,而centos7默认systemd是216版本,这俩东西不兼容,导致systemctl无法正常使用。

老外在https://github.com/docker/for-mac/issues/6073 中提出了这个问题,开始以为是mac的问题,后来发现在ubuntu20.10中也有这个问题。于是大家开始找解决方法。
这里的解决方法在刚才已经提到,就是升级systemd版本,或者使用映射把容器的cgroup放出来给docker desktop用。

当然,后来鉴于centos7属于主流操作系统,用的人太多了,维护者在settings.json中加入了对cgroup v1的兼容。改一个配置就能解决此问题,不用映射/sys/fs/cgroup也不用升级systemd了。

在docker desktop 4.4.2版本的公告中可以看到解决方法:

Added a deprecated option to settings.json: “deprecatedCgroupv1”: true, which switches the Linux environment back to cgroups v1. If your software requires cgroups v1, you should update it to be compatible with cgroups v2. Although cgroups v1 should continue to work, it is likely that some future features will depend on cgroups v2. It is also possible that some Linux kernel bugs will only be fixed with cgroups v2.

0x03 解决方案

具体操作如下:
编辑~/Library/Group\ Containers/group.com.docker/settings.json修改"legacyCgroupv1"参数为true,默认是false

legacyCgroupv1: true,

0x04 参考文献

https://github.com/docker/for-mac/issues/6073
https://github.com/scylladb/scylladb/issues/7071
https://bugzilla.redhat.com/show_bug.cgi?id=1760645
https://www.leyeah.com/article/cgroups-dockerprinciple-677345
https://www.cnblogs.com/sparkdev/p/9523194.html
https://ehds.github.io/2021/01/21/docker_systemctl/
https://www.infoq.cn/article/fuoi4c3l0npztxarhjnn
https://zorrozou.github.io/docs/%E8%AF%A6%E8%A7%A3Cgroup%20V2.html
https://zhuanlan.zhihu.com/p/143253843

猜你喜欢

转载自blog.csdn.net/counsellor/article/details/128448999