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

d-bus-permitted
d-bus-permitted

方法1:前台启用

 1[root@ecs-82f5]~# docker run -itd centos:7
 2c7b7404702322146e9c53a2fafb89dd4dd2dc7d3996dd4c7d62c9c14dff44961
 3[root@ecs-82f5]~# docker ps
 4CONTAINER ID   IMAGE           COMMAND       CREATED         STATUS         PORTS     NAMES
 5c7b740470232   centos:7        "/bin/bash"   3 seconds ago   Up 2 seconds             wizardly_kare
 6[root@ecs-82f5]~# docker exec -it c7b740470232 /bin/bash
 7或者docker attach c7b740470232也是一样的
 8[root@c7b740470232 /]# yum -y install httpd
 9[root@c7b740470232 /]# systemctl start httpd
10Failed to get D-Bus connection: Operation not permitted
11[root@c7b740470232 /]# httpd -D FOREGROUND
12AH00558: 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时,对应的内容为:

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

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

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

 1FROM centos:centos7
 2LABEL maintainer="yangbk <itybku>"
 3
 4ENV nginxversion="1.12.2-1" \
 5    os="centos" \
 6    osversion="7" \
 7    elversion="7_4"
 8
 9RUN yum install -y wget openssl sed &&\
10    yum -y autoremove &&\
11    yum clean all &&\
12    wget http://nginx.org/packages/$os/$osversion/x86_64/RPMS/nginx-$nginxversion.el$elversion.ngx.x86_64.rpm &&\
13    rpm -iv nginx-$nginxversion.el$elversion.ngx.x86_64.rpm &&\
14    sed -i '1i\
15    daemon off;\
16    ' /etc/nginx/nginx.conf
17
18CMD ["nginx"]
19</itybku>

方法2:给特定权限

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

1[root@ecs-82f5]~# docker run -d --name centos7 --privileged=true centos:7 /usr/sbin/init
2[root@ecs-82f5]~# docker exec -it centos7 /bin/bash
3[root@f11a431747f5 /]# yum -y install vsftpd
4[root@f11a431747f5 /]# systemctl start vsftpd
5[root@f11a431747f5 /]# ps auxf|grep vsftpd
6root       159  0.0  0.0   9092   676 pts/0    S+   21:53   0:00  \_ grep --color=auto vsftpd
7root       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
rocky-dbus

错误原因分析

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

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

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