关于docker使用的几个小问题(二)

本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃

 

  很久没写博客了,集中写几个比较有意思的小问题。

一、CentOS容器没有service命令

  这是因为我们从docker官方镜像仓库中pull的最新CentOS镜像都是centos7.4 Redhat-release,Redhat已经通过systemclt命令取代了service命令,所以如果需要运行service命令,可以通过systemctl来替换。如以下这两条关于Apache的命令是等效的。

service httpd status
systemctl status httpd

  有的同学会说,为什么我本地装的centos可以使用service?ok,如果一定要用service也不是没有解决方案:

yum install -y initscripts.x86_64

  把它装上就可以用了,只是让你用着舒服,其实它还是通过systemctl来执行。

二、CentOS容器没有pidof命令

  这是因为官方的镜像是精简版的,没有提供pidof所在的指令集,如果需要使用,也是需要安装的:

yum install -y redhat-lsb

三、 Failed to get D-Bus connection: Operation not permitted

  当我们在CentOS7上执行systemctl命令就会产生这个错误,上面两个问题其实和这个问题原因产生的是一致的,尤其是关于这个问题,网上给出诸多说法,我来给大家一个官方的说法。首先不要急,我先给性子急的同学几个解决方案:

  方案一:

docker run -d -e "container=docker" --privileged=true -v /sys/fs/cgroup:/sys/fs/cgroup --name centos7 centos /usr/sbin/init
###对安全问题比较关心的同学,建议将--privileged=true替换为--cap-add=SYS_ADMIN

  方案二:

docker run -ti --privileged centos init
#或者
docker run -ti --privileged centos /usr/lib/systemd/systemd
#或者
docker run -ti --cap-add=SYS_ADMIN cents init

  大家会说,方案二怎么卡住了,没关系,不用管它,重启一个连接exec到容器中即可,原来的窗口关掉就行。

  方案三:

FROM fedora:rawhide
MAINTAINER “Dan Walsh” <dwalsh@redhat.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”]

  写一个dockerfile,这段dockerfile是有来历的,它的作用就是生成一个可以调用systemctl的CentOS容器,同时删除了一些不必要的系统进程。在上面的指令中,我们经常看到/sbin/init,它是什么东东呢:

  之所以报这个d-bus的错误就是因为在容器中,CentOS的镜像是默认不启动systemd的,而且启动需要privileged权限或者--cap-add=SYS_ADMIN权限。 Docker依赖Linux内核的功能:容器和宿主机建立相互隔离的环境(应用程序在里面运行)。而官方的容器很精简,容器之所以和宿主机共享同一内核,却在不同的运行时环境中执行,这归功于控制组(cgroup)和命名空间,它们定义了容器可以使用哪些资源,与此同时,容器本身只能看到某些进程和网络功能。所以我们可以看到前面第一个命令,在privileged的同时还进行了cgroup目录的挂载,这就是定义了该容器获取了系统的完整内核。

  下面我就给大家讲讲Redhat和Docker的那点故事,不喜欢八卦的同学可以不用看了啊:

  八卦的主人是一个叫Daniel Walsh的老头,Daniel在Redhat专门从事容器安全工作,https://developers.redhat.com/blog/2014/05/05/running-systemd-within-docker-container/这篇文章是他在2014年所写,前面的那个dockerfile就是他在解决这个问题时的成果之一,文章写作时这个“bug”是以更严重的segment呈现的,而https://lwn.net/Articles/676831/https://developers.redhat.com/blog/author/rhatdan/,Daniel道出了关于systems和docker的冲突(因为这个老头是直接受害人。。。毕竟他的主要工作就是磨合systemd和docker,哈哈)。反正我是看着头大,简单来说大概就是Docker守护进程旨在接管系统还为Linux执行的很多功能,而Redhat担心docker的安全性,所以在内核作出了诸多限制,最直观的一个体现就是在systemd的使用上。

  这个图是我在Daniel博客上的截图,从中我们可以看到Redhat和docker的开发者在扯皮,挺有意思,更多扯皮欢迎大家围观https://lwn.net/Articles/676831/,老头也是挺不容易,夹在中间多难受啊。

  回到一开始,我们知道centos是基于Redhat内核的,所以才会造成这个问题。解决方案我刚开始已经给出了,这里还是一个使用机制的问题,不管是docker开发者还是Redhat的开发者,其实他们都期望用户在一个docker里只运行一个服务,所以最好的解决办法其实还是通过dockerfile,每个服务通过dockerfile来安装并在dockerfile中启动(CMD )。
但是安全问题始终是绕不过去的,docker和Redhat给出了一些建议:http://cloud.51cto.com/art/201501/464287.htm,希望对有深入了解需求的同学有所帮助。 

 四、恩,我只是一个搞深度学习的围观吃瓜群众。。。 

posted @ 2017-10-31 00:30  负赑屃  阅读(2980)  评论(0编辑  收藏  举报