解决Docker报错Failed D-Bus: Operation not permitted

在centos docker image里,通过systemctl start httpd这样的指令启动服务,经常会遇到Failed to get D-Bus connection: Operation not permitted这样的报错,这里就结合示例,给出下解决方法。

d-bus-permitted

方法1:前台启用

[root@ecs-82f5]~# docker run -itd centos:7
c7b7404702322146e9c53a2fafb89dd4dd2dc7d3996dd4c7d62c9c14dff44961
[root@ecs-82f5]~# docker ps
CONTAINER ID   IMAGE           COMMAND       CREATED         STATUS         PORTS     NAMES
c7b740470232   centos:7        "/bin/bash"   3 seconds ago   Up 2 seconds             wizardly_kare
[root@ecs-82f5]~# docker exec -it c7b740470232 /bin/bash
或者docker attach c7b740470232也是一样的
[root@c7b740470232 /]# yum -y install httpd
[root@c7b740470232 /]# systemctl start httpd
Failed to get D-Bus connection: Operation not permitted
[root@c7b740470232 /]# httpd -D FOREGROUND
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message

从上面可以看出,把systemctl的启动方式,改为了httpd前台启动方式后,就可以正常使用了,这在写dockerfile时,对应的内容为:

Docker容器启动web服务时,都指定了前台运行的参数,例如apache:
ENTRYPOINT [ "/usr/sbin/apache2" ]
CMD ["-D", "FOREGROUND"]
又例如nginx:
ENTRYPOINT [ "/usr/sbin/nginx", "-g", "daemon off;" ]

因为Docker容器仅在它的1号进程(PID为1)运行时,会保持运行。如果1号进程退出了,Docker容器也就退出了。一定要注意daemon off ;分号不能去掉!否则失败!!

这里也给个nginx配置的Dockerfile示例,这里是通过修改配置文件nginx.conf实现的:

FROM centos:centos7
LABEL maintainer="yangbk <itybku@139.com>"
ENV nginxversion="1.12.2-1" \
    os="centos" \
    osversion="7" \
    elversion="7_4"
RUN yum install -y wget openssl sed &&\
    yum -y autoremove &&\
    yum clean all &&\
    wget http://nginx.org/packages/$os/$osversion/x86_64/RPMS/nginx-$nginxversion.el$elversion.ngx.x86_64.rpm &&\
    rpm -iv nginx-$nginxversion.el$elversion.ngx.x86_64.rpm &&\
    sed -i '1i\
    daemon off;\
    ' /etc/nginx/nginx.conf
CMD ["nginx"]

方法2:给特定权限

启动时给privileged权限,并指定/usr/sbin/init,这样启动就不会报错了。

[root@ecs-82f5]~# docker run -d --name centos7 --privileged=true centos:7 /usr/sbin/init
[root@ecs-82f5]~# docker exec -it centos7 /bin/bash
[root@f11a431747f5 /]# yum -y install vsftpd
[root@f11a431747f5 /]# systemctl start vsftpd
[root@f11a431747f5 /]# ps auxf|grep vsftpd
root       159  0.0  0.0   9092   676 pts/0    S+   21:53   0:00  \_ grep --color=auto vsftpd
root       155  0.0  0.0  53292   572 ?        Ss   21:52   0:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf

这个问题在centos/redhat/rocky等相关版本里比较明显,而debian/ubuntu等相关系统处理的相对更好一些,其通过service和systemctl指令启停服务,但未出现该报错。

rocky Linux下的报错内容如下:

rocky-dbus

错误原因分析

Docker 的设计理念是不在容器中运行后台服务。容器本身是宿主机上一个独立的主进程。也可以间接理解为容器中运行服务的应用进程。

容器的生命周期围绕着主进程,所以使用容器的正确方法是在前台运行容器内部的服务。 systemd 维护一个系统服务程序,它需要访问 Linux 内核的权限。而且容器不是一个完整的操作系统,只有一个文件系统,默认启动只供普通用户访问Linux内核。

因此,请遵循容器设计原则,在容器中运行前台服务!

发表评论

您的电子邮箱地址不会被公开。