Docker中无法获取systemctl权限的问题

据说在 Linux Docker中无法使用 systemd(systemctl) 相关命令的原因是 1号进程不是 init ,而是其他例如 /bin/bash ,所以导致缺少相关文件无法运行。(System has not been booted with systemd as init system (PID 1). Can’t operat)

解决方案:/sbin/init

例如:Ubuntu 18.04 ,

docker run -tid –name test –privileged=true ubuntu:18.04 /sbin/init
docker exec -it test /bin/bash

PS:–privilaged=true一定要加上的。

目标

项目需要用到Xvfb,而安装Xvfb需要systemctl权限。

安装Xvfb

参考自这个文章:https://serverdiary.com/linux/how-to-install-xvfb-and-create-systemd-xvfb-service-on-centos-7-8-or-rhel-7-8/

先通过yum安装Xvfb

/etc/systemd/system/xvfb.service里面有个默认的浏览器大小?

docker run –network=host -tid xvfb

一直到这一步,报错了:

1
2
systemctl daemon-reload
Failed to get D-Bus connection: Operation not permitted

这个文章提到,需要重新制作镜像,并设置权限参数:

https://serverfault.com/questions/824975/failed-to-get-d-bus-connection-operation-not-permitted

/home/share/dockerfile/xvfb.Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM xvfb
MAINTAINER "zhouchangju" <zhouchangju@myhexin.com>
ENV container docker
#RUN yum -y update; yum clean all
RUN yum -y install systemd; yum clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]

构建镜像:

1
docker build --rm -t xvfb-systemd - < xvfb.Dockerfile 

启动新的镜像:

1
docker run --privileged --network=host  -ti -e container=docker  -v /sys/fs/cgroup:/sys/fs/cgroup  xvfb-systemd /usr/sbin/init

但是启动时,我又遇到一个新的问题:

1
2
Couldn't find an alternative telinit implementation to spawn.
/usr/sbin/init exited 1

这是执行/usr/sbin/init的时候报的错误;如果不执行这个,无法获取systemctl权限

网上说是因为需要包含 Volume(卷) /sys/fs/cgroup;但是我已经加了,还是不行

是否不用加入系统服务?

可以直接启动:

1
2
3
docker run --privileged --name xvfb --network=host  -tid -e container=docker  -v /sys/fs/cgroup:/sys/fs/cgroup -v /opt/google/chrome/chrome_extension:/opt/google/chrome/chrome_extension -v /home/share/puppeteer/:/home/share/puppeteer/ -v /home/share/video/:/root/Downloads/ xvfb-systemd

docker exec -ti xvfb /bin/bash

启动Xvfb:

1
2
# 注意这里设置的分辨率,是会影响最终生成的视频的分辨率的,这个待琢磨
Xvfb -ac :7 -screen 0 1280x1024x8

然后执行node puppeteer.js录屏,发现报错了:Unable to open X display

经测试,发现还需要我们主动启动浏览器:

1
export  DISPLAY=:7 (和上一步的number号相同)

现在执行node puppeteer.js,就可以录屏了。

但是查看录制好的视频,只有20K,播放是一片白的。怀疑是Puppeteer启动浏览器的时候设置太大了,导致屏幕中间的位置并没有内容。

将Puppeteer打开的浏览器页面设置小之后再测试,果然有内容了。

但是有个新的问题:scale似乎针对录制没效果,怀疑是因为没有重启Xvfb,导致修改的插件内容没有重新加载生效。

重启Xvfb,再次录屏,还是不对,页面中的绘图部分仍然很小,看起来是没有scale的效果。

将Puppeteer打开的浏览器设置小一点,发现就可以了。

问题:

我将Xvfb的启动分辨率设置大了后,确实录制的界面大了,但是帧数非常低,最终生成的文件反而比低分辨率更小了。

1
Xvfb -ac :7 -screen 0 4800x2500x8

Xvfb文档:https://www.x.org/releases/X11R7.6/doc/man/man1/Xvfb.1.xhtml#heading4

当Xvfb启动的分辨率设置大了后,效果非常明显,很清晰,就是帧数严重下降了。因此我们需要一个强劲的CPU才行。不知道线上docker的CPU怎么样。

经测试,Xvfb设置的分辨率越大,耗费的CPU和性能就越高,因此我们应该合理设置这个数值,否则会导致资源浪费,帧数降低。