Docker之風席捲全球,但不少人以爲docker入門確實不太容易,其緣由在於不少知識點上沒準備好,在docker解決了什麼問題、怎麼解決的、用什麼技術解決的都還沒想清楚的時候就去探索docker組件原理,天然會犯迷糊,與其迷茫地步履維艱,不如先看看知識準備,入門了繼續進行研究。
Docker是一種在Linux容器裏運行應用的開源工具,一種輕量級的虛擬機。除了運行應用,Docker還提供了一些工具,藉助Docker Index或本身託管的Docker註冊表對進行了集裝箱化處理的應用進行分發,從而簡化複雜應用的部署過程。
本文將介紹現在在部署複雜系統時公司所面臨的挑戰,Docker怎樣有效地解決這個問題,在宏觀上對docker項目進行介紹,並發表一些本身理解的見解。以後的文章會慢慢深刻,對docker模塊逐個剖析。html
容器指用來包裝或裝載物品的貯存器(如箱、罐、壇)或者成形或柔軟不成形的包覆材料。在web環境中,容器是應用服務器中位於組件和平臺之間的接口集合。在docker級別,容器能夠理解爲一個邊界,邊界裏面是所想運行的各類程序,邊界外面是基礎環境,邊界裏外儘可能少的耦合。 nginx
服務器應用的部署已經愈來愈複雜了。把幾個Perl腳本拷貝到正確目錄就完成服務器應用的安裝,這種時代已經一去不復返了。現在的軟件有不少類型的需求:
對已安裝軟件和庫的依賴(「Python版本高於2.6.3,使用Django 1.2」)
依賴於正在運行的服務(「須要一個MySQL 5.5數據庫和一個RabbitMQ隊列」)
依賴於特定的操做系統(「在64位的Ubuntu Linux 12.04上構建、測試」)
資源需求:
最小的可用內存(「須要1GB的可用內存」)
能綁定特定的端口(「綁定80和443端口」)
咱們來看一個相對簡單的應用的部署:Wordpress。Wordpress的安裝一般要求: web
在服務器上部署、運行這樣一個系統,咱們可能會遇到下面的問題和挑戰:
隔離性:若是咱們已經在這個服務器上部署了不一樣的網站,已有的網站只能在nginx上 運行,而Wordpress依賴於Apache,這時咱們就會有麻煩:它們都監聽80端口。同時運行兩個網站是能夠的,但須要調整配置(修改監聽端口), 設置反向代理等。庫級別也會出現相似的衝突,若是還要運行一個仍然依賴PHP4的老應用就會出問題,由於Wordpress再也不支持PHP4,同時運行 PHP4和PHP5則很是困難。運行在同一個服務器上的應用沒有互相隔離(在文件系統級別和網絡級別),因此它們可能會互相沖突。
**安全性:**Wordpress的安全記錄並非很是好。因此仍是給它建立個沙箱,至少黑客入侵時不會影響其餘運行的應用。
升級、降級:升級應用通常會覆蓋現有文件。升級過程當中會發生什麼?系統要關閉麼?若是升級失敗,或者不對該怎麼辦?咱們怎樣快速回退到先前的版本?
快照、備份:一旦全部的內容都設置好,就給系統建立一個「快照」,以便能備份快照,甚至能移到另外一個服務器上再次啓動,或者拷貝到多個服務器上以備不時之需。
重複性:系統出新版本以後,比較好的作法是先在測試基礎設施上自動部署並測試,而後再發布到生產系統。一般會利用諸如Chef、Puppet等 工具在服務器上自動安裝一堆包,等一切內容都就緒後,再在生產系統上運行相同的部署腳本。這在百分之九十九的狀況下都沒有問題。但有百分之一的例外,在部 署到測試環境和生產環境之間的時間跨度裏,你依賴的包在包倉庫裏有了更新,而新版本並不兼容。結果生產環境的設置和測試環境不一樣,還有可能破壞生產系統。 假如沒有控制部署的每個方面(例如託管本身的APT或YUM倉庫),持續在多個階段(好比測試、預演、生產環境)重複搭建出徹底相同的系統就很困難。
資源限制:若是咱們的Wordpress耗費CPU資源,並佔用了全部的CPU週期,致使其餘應用沒法作任何事情怎麼辦?若是它用盡了所有可用的內存呢?或者瘋狂寫日誌阻塞磁盤呢?要是能限制應用的可用資源,好比CPU、內存和磁盤空間,就會很是方便。
易於安裝:也許有Debian或CentOS包,抑或是能自動執行全部複雜步驟並安裝 Wordpress的Chef菜譜。但這些菜譜很難穩定下來,由於它們須要考慮目標系統上可能的系統配置。不少狀況下,這些菜譜只能在乾淨的系統上運行。 所以,你不太可能更換成本身的包或Chef菜譜。這樣的話,安裝就是個複雜的系統工程,而不是午休期間就能搞定的事情。
易於移除:軟件應該能輕鬆、乾淨地移除,不留痕跡。但部署應用一般要調整已有的配置文件、設置狀態(MySQL數據庫的數據,日誌),徹底移除應用也變得不那麼容易。
那咱們應該如何解決這些問題呢?docker
咱們決定在單獨的虛擬機上運行獨立的應用,例如Amazon的EC2,大部分問題這時會迎刃而解:
隔離性:在一個VM上安裝一個應用,應用是徹底獨立的,除非它們攻入了對方的防火牆。
重複性:用你喜歡的方式準備系統,而後建立一個AMI。你能夠隨意實例化多個AMI實例。徹底是可重現的。
安全性:因爲咱們徹底隔離,若是Wordpress遭到攻擊,其他的基礎設施並不會受到影響——除非你沒有保管好SSH密鑰或者在哪裏都使用同一個密碼,但你應該不會這麼作吧?
**資源限制:**VM會分配特定的CPU週期、可用內存和磁盤空間,沒有加價的話就不能超額。
易於安裝:愈來愈多的應用可以在EC2上運行,只要在AWS marketplace上點擊一個按鈕就能實例化應用。啓動只須要幾分鐘,就是這樣。
易於移除:不須要某個應用了?銷燬VM。乾淨又方便。
**升級、降級:**Netflix如何部署代碼裏提到,只須要在新VM上部署新版本,而後讓負載均衡器指向部署了新版本的VM。不過應用若是須要在本地保存狀態,這種方法就不是很好用了。
快照、備份:點擊一個按鈕(或者調用一下API)就能得到EBS磁盤的快照,快照會備份到S3中。
完美!
不過……咱們有個新問題:虛擬機在兩個方面比較昂貴:
金錢:你真的有那麼多錢爲每一個應用啓動一個EC2實例?另外你能預測到須要多少個實例麼?若是你之後須要更多的資源,你須要中止VM進行升級——不然就要爲閒置資源白白付錢,直到真正用起來(除非你用能動態調整大小的Solaris Zones,好比Joyent上的)。
時間:虛擬機相關的操做大多都很慢:啓動要幾分鐘,捕捉快照要幾分鐘,建立鏡像也須要幾分鐘。世界不停轉動,咱們可沒有這種時間!
咱們能作得更好嗎?數據庫
Docker是由公共PaaS提供商dotCloud的人發起的開源項目,於去年初發起。從技術角度來講,Docker(主要用Go語言編寫)試圖簡化兩種已有技術的使用:
**LXC:**Linux容器,容許獨立進程在比普通Unix進程更高的隔離級別上運行。使用的技術術語是集裝箱化:一個容器裏運行一個進程。容器支持的隔離級別有:
文件系統:容器只能訪問本身的沙箱文件系統(相似於chroot),不然要專門掛載到容器的文件系統中才能訪問。
用戶名字空間:容器有本身的用戶數據庫(也就是容器的root不等於主機的root帳戶)。
進程名字空間:只有容器裏的進程纔是可見的(ps aux的輸出會很是簡潔)。
網絡名字空間:每一個容器都有本身的虛擬網絡設備和虛擬IP(所以它能夠綁定任意端口,不用佔用主機端口)。
AUFS:高級多層的統一文件系統,可用來建立聯合、寫時拷貝的文件系統。
Docker能夠安裝在任何支持AUFS和內核版本大於等於3.8的Linux系統上。但從概念上來講它並不依賴於這些技術,之後也能夠和相似的技術一塊兒運行,例如Solaris的Zones或BSD jails,並將ZFS做爲文件系統。不過目前只能選擇Linux 3.8+和AUFS。安全
Docker很是輕量。啓動VM是個大動做,須要佔用大量內存;而啓動Docker容器只耗費不多的CPU和內存,而且很是快。幾乎和啓動一個常規進程沒什麼區別。不只運行容器快,構建鏡像、捕獲文件系統的快照也很快。
它運行在已經虛擬化過的環境中。也就是說,你能夠在EC2實例、Rackspace VM或VirtualBox裏運行Docker。事實上,在Mac和Windows上使用Docker的首選方式是使用Vagrant。
Docker容器能移植到任何運行Docker的操做系統上。不管是Ubuntu仍是CentOS,只要Docker運行着,你的容器就能運行。
讓咱們回到前面的部署、操做問題列表,看看Docker是怎麼解決的:
隔離性:Docker在文件系統和網絡級別隔離了應用。從這個意義上來說很像在運行」真正的「虛擬機。
重複性:用你喜歡的方式準備系統(登陸並在全部軟件裏執行apt-get命令,或者使用Dockerfile),而後把修改提交到鏡像中。你能夠隨意實例化若干個實例,或者把鏡像傳輸到另外一臺機器,徹底重現一樣的設置。
**安全性:**Docker容器比普通的進程隔離更爲安全。Docker團隊已經肯定了一些安全問題,正在着手解決。
**資源約束:**Docker如今能限制CPU的使用率和內存用量。目前還不能直接限制磁盤的使用狀況。
**易於安裝:**Docker有一個Docker Index,這個倉庫存儲了現成的Docker鏡像,你用一條命令就能夠完成實例化。好比說,要使用Clojure REPL鏡像,只要運行docker run -t -i zefhemel/clojure-repl命令就能自動獲取並運行該鏡像。
易於移除:不須要應用了?銷燬容器就行。
升級、降級:和EC2 VM同樣:先啓動應用的新版本,而後把負載均衡器切換到新的端口。
**快照、備份:**Docker能提交鏡像並給鏡像打標籤,和EC2上的快照不一樣,Docker是當即處理的。服務器
Namespace定義與概念
每一個用戶實例之間相互隔離, 互不影響。 通常的硬件虛擬化方法給出的方法是VM,而LXC給出的方法是container,更細一點講就是kernel namespace。其中pid、net、ipc、mnt、uts、user等namespace將container的進程、網絡、消息、文件系統、UTS(「UNIX Time-sharing System」)和用戶空間隔離開。
Cgroups定義與概念
cgroups 實現了對資源的配額和度量。 cgroups 的使用很是簡單,提供相似文件的接口,在 /cgroup目錄下新建一個文件夾便可新建一個group,在此文件夾中新建task文件,並將pid寫入該文件,便可實現對該進程的資源控制。 groups能夠限制blkio、cpu、cpuacct、cpuset、devices、freezer、memory、net_cls、ns九大子系 統的資源
AUFS定義與概念
AUFS (AnotherUnionFS) 是一種 Union FS, 簡單來講就是支持將不一樣目錄掛載到同一個虛擬文件系統下(unite several directories into a single virtual filesystem)的文件系統, 更進一步的理解, AUFS支持爲每個成員目錄(相似Git Branch)設定readonly、readwrite 和 whiteout-able 權限, 同時 AUFS 裏有一個相似分層的概念, 對 readonly 權限的 branch 能夠邏輯上進行修改(增量地, 不影響 readonly 部分的)。一般 Union FS 有兩個用途, 一方面能夠實現不借助 LVM、RAID 將多個disk掛到同一個目錄下, 另外一個更經常使用的就是將一個 readonly 的 branch 和一個 writeable 的 branch 聯合在一塊兒,Live CD正是基於此方法能夠容許在 OS image 不變的基礎上容許用戶在其上進行一些寫操做 網絡
儘管Docker有助於系統的可靠部署,但它自己並非個徹底成熟的部署系統。它操做的是容器裏運行的應用。哪一個容器安裝在哪一個服務器上,以及如何啓動它們,則超出了Docker的範圍。
一樣的,Docker也不處理跨多個容器(可能在多個物理服務器上,也可能在多個VM上)運行的應用。要讓容器互相通訊,須要某些發現機制,來找出哪些IP和端口上的其餘應用可用。這和跨常規虛擬機的服務發現很是類似。etcd等工具,或者其餘的服務發現機制都能用來解決這個問題。架構
雖然Docker目前默認使用LXC和AUFS,可是Docker的核心思想自己,並不強制綁定這二者,0.8版本已經可使用BTRFS,而整個Docker框架也改爲了插件式的架構,便於添加替換各個功能模塊 併發
例如更多的Storage方案的支持,規避AUFS當前的問題,除了LXC之外更多的虛擬化方案等
容器實質上是一個職責劃分的工具。Docker與容器不是等價的,docker是容器,但容器不只僅指的是docker,docker爲容器的一個表明,我的理解的docker主要解決的問題爲以下兩方面
一、不一樣層之間的依賴關係解耦;例如:安裝、移除、重複利用。以下圖中,container與Host OS和Server之間的解耦。
二、同層之間資源隔離與資源限制;例如:端口、cpu搶佔,同服站點互不影響。下圖中App A與APP B之間的隔離,和APP各自的資源利用限制。
容器解決的問題虛擬機已所有解決,爲何還須要容器docker呢?緣由是虛擬機在架構上過重,在資源上有不少沒必要要的花費,在時間上啓動、建立鏡像、快照等消耗較長,在層次結構上虛擬機只具備一層封裝,將操做系統、服務、應用所有封裝,並不能靈活的拆卸與組裝,職責劃分並不明確。
Docker略帶積木化色彩,將雜糅的運行環境積木化,用於更快更好的搭建和複用。
Docker容器http://www.infoq.com/cn/articles/docker-containers
http://blog.csdn.net/colorant/article/details/20608157
LXC 入門文章http://www.cnblogs.com/lisperl/archive/2012/04/15/2450183.html
Docker核心技術預覽:http://www.infoq.com/cn/articles/docker-core-technology-preview