本文為作者原創,轉載請注明出處(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/,老頭也是挺不容易,夾在中間多難受啊。
四、恩,我只是一個搞深度學習的圍觀吃瓜群眾。。。