相對于VM,docker在其輕量、配置復雜度以及資源利用率方面有著明顯的優勢。 隨著docker技術的不斷成熟,越來越多的企業開始考慮通過docker來改進自己的IT系統。
本文列舉一些docker的實際應用場景,以期能夠起到拋磚引玉的作用, 來幫助大家更加方便的使用docker。
應用打包
制作過RPM、GEM等軟件包的同學可能很清楚,每一個軟件包依賴于哪個庫的哪個版本, 往往需要明確的寫在依賴列表里。而依賴又往往分為編譯時依賴和運行時依賴。
在傳統的基礎設施環境下,為了保證所生成的軟件包在其它機器上可正常安裝且運行, 一般需要在打包之前創建個干凈的虛擬機,或者手工創建個chroot環境, 然后在這個干凈的環境下安全各種依賴包,然后執行打包腳本。 生成軟件包以后,需要再創建一個干凈的環境安裝、運行這個軟件包,來驗證是否符合預期。 這樣雖然也能完成打包工作,但至少有以下缺點:
耗時耗力
依賴關系容易漏掉,比如:在干凈的環境中經過多次調試,把缺少的依賴包一個一個的裝上了, 但最后寫spec文件時卻忘記添加某個依賴,導致下次打包時需要重新調試或者打包后軟件包無法使用等問題。
通過docker可以很好的解決打包問題。具體作法如下:
“干凈的打包環境”很容易準備,docker官方提供的ubuntu、centos等系統鏡像天生就能作為純凈無污染的打包環境使用
Dockerfile本身能起到文檔固化的作用,只要寫好Dockerfile,創建好打包鏡像,以后就能無限次重復使用這個鏡像進行打包
示例:
我們要為某個PHP擴展模塊(如:php-redis)制作個RPM包。
首先,需要寫個用于創建打包鏡像的Dockerfile, 內容如下:
FROM centos:centos6
RUN yum update -y
RUN yum install -y php-devel rpm-build tar gcc make
RUN mkdir -p /rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} &&
echo '%_topdir /rpmbuild' >~/.rpmmacros
ADD http://pecl.php.net/get/redis-2.2.7.tgz/rpmbuild/SOURCES/redis-2.2.7.tgz
ADD https://gist.githubusercontent.com/mountkin/5175c213585d485db31e/raw/02f6dce79e12b692bf39d6337f0cfa72813ce9fb/php-redis.spec/redis.spec
RUN rpmbuild -bb /redis.spec
然后執行docker build -t php-redis-builder ., 執行成功后,就會生成我們需要的RPM包。
接下來,執行以下命令把生成的軟件包從docker鏡像中復制出來:
[ -d /rpms ] || mkdir /rpms
docker run --rm -v /rpms:/rpms:rw php-redis-builder cp /rpmbuild/RPMS/x86_64/php-redis-2.2.7-1.el6.x86_64.rpm /rpms/
然后/rpms目錄下就會有我們剛剛制作的RPM包。
最后,軟件包的驗證過各也非常簡單,只需要新創建一個docker鏡像,把新生成的軟件包添加進去并安裝即可。
Dockerfile如下(為了ADD RPM文件,需要保存在/rpms目錄下):
FROM centos:centos6
ADD php-redis-2.2.7-1.el6.x86_64.rpm /php-redis-2.2.7-1.el6.x86_64.rpm
RUN yum localinstall -y /php-redis-2.2.7-1.el6.x86_64.rpm
RUN php -d "extension=redis.so" -m |grep redis
在/rpms目錄下執行docker build -t php-redis-validator .,如果執行成功,則表明RPM包可正常工作。
多版本混合部署
隨著產品的不斷更新換代,一臺服務器上部署多個應用或者同一個應用的多個版本在企業內部非常常見。
但一臺服務器上部署同一個軟件的多個版本,文件路徑、端口等資源往往會發生沖突,造成多個版本無法共存的問題。
如果用docker,這個問題將非常簡單。由于每個容器都有自己獨立的文件系統,所以根本不存在文件路徑沖突的問題; 對于端口沖突問題,只需要在啟動容器時指定不同的端口映射即可解決問題。
升級回滾
一次升級,往往不僅僅是應用軟件本身的升級,通過還會包含依賴項的升級。 但新舊軟件的依賴項很可能是不同的,甚至是有沖突的,所以在傳統的環境下做回滾一般比較困難。
如果使用docker,我們只需要每次應用軟件升級時制作一個新的docker鏡像,升級時先停掉舊的容器, 然后把新的容器啟動。 需要回滾時,把新的容器停掉,舊的啟動即可完成回滾,整個過程各在秒級完成,非常方便。
多租戶資源隔離
資源隔離對于提供共享hosting服務的公司是個強需求。 如果使用VM,雖然隔離性非常徹底,但部署密度相對較低,會造成成本增加。
docker容器充分利用linux內核的namespaces提供資源隔離功能。
結合cgroup,可以方便的設置某個容器的資源配額。 既能滿足資源隔離的需求,又能方便的為不同級別的用戶設置不同級別的配額限制。
但在這種應用場景下,由于容器中運行的程序對于hosting服務提供方來說是不可信的, 所以需要特殊的手段來保證用戶無法從容器中操作到宿主機的資源(即:越獄,盡管這種問題發生的概率很小,但安全無小事,多一層防護肯定讓人更加放心)。
安全及隔離性加固方面,可考慮以下措施:
通過iptables阻斷從容器到所有內網IP的通信(當然如果需要也可以針對特定的IP/端口開放權限)
通過selinux或者apparmor限制某個容器所能訪問的資源
對某些sysfs或者procfs目錄,采用只讀方式掛載
通過grsec來加固系統內核
通過cgroup對內存、CPU、磁盤讀寫等資源進行配額控制
通過tc對每個容器的帶寬進行控制
另外我們在實際測試中發現系統的隨機數生成器很容易因熵源耗盡而發生阻塞。 在多租戶共享環境下需要在宿主機上啟用rng-tools來補充熵源。
這個應用場景下有很多工作是docker本身所不能提供的,并且實施起來需要關注的細節比較多。 為此我們提供了安全加強版docker管理平臺,可完美解決以上問題。 需要的朋友可以通過csphere官網了解更多細節。
內部開發環境
在容器技術出現之前,公司往往是通過為每個開發人員提供一臺或者多臺虛擬機來充當開發測試環境。
開發測試環境一般負載較低,大量的系統資源都被浪費在虛擬機本身的進程上了。
docker容器沒有任何CPU和內存上的額外開銷,很適合用來提供公司內部的開發測試環境。
而且由于docker鏡像可以很方便的在公司內部分享,這對開發環境的規范性也有極大的幫助。
如果要把容器作為開發機使用,需要解決的是遠程登錄容器和容器內進程管理問題。 雖然docker的初衷是為“微服務”架構設計的,但根據我們的實際使用經驗, 在docker內運行多個程序,甚至sshd或者upstart也是可行的。
這方面csphere也有成熟的產品及解決方案,歡迎感興趣的朋友試用反饋。
后記
以上總結了我們在實際開發和生產環境中使用docker的一些場景, 以及在每種情況下遇到的問題和相應的解決方法,希望對有意使用docker的朋友有所啟發。 同時我們也歡迎更多的朋友分享關于docker的使用經驗。(責編:劉亞瓊)
作者: 魏世江, NiceScale聯合創始人,長期從事DevOps相關研發工作。 專注于Linux環境Web應用及周邊服務的配置管理自動化。擅長使用go語言及PHP語言, 對容器技術有一定的研究,目前正集中精力做基于docker的企業級解決方案。 創業之前在新浪云平臺(SAE)任技術經理。歡迎志同道合的朋友以各種方式勾搭騷擾。
原文鏈接: https://blog.nicescale.com/docker-use-cases/
OpenCloud 2015將于2015年 4月16-18日在北京召開。大會包含“2015 OpenStack技術大會”、“2015 Spark技術峰會”、“2015 Container技術峰會”三大技術峰會及多場深度行業實戰培訓,主題聚焦技術創新與應用實踐,薈萃國內外真正的云計算技術的大牛講師。這里都是一線接地氣的干貨,扎實的產品、技術、服務和平臺。OpenCloud 2015,懂行的人都在這里!
更多講師和日程信息請關注OpenCloud 2015介紹和官網。