開始學習docker了,想寫一篇docker技術介紹的純理論文章,發現如下網站的文檔寫的特別好,就直接引用了,文章轉載自:html
http://www.infoq.com/cn/DockerDeep node
http://www.infoq.com/cn/articles/docker-core-technology-preview?python
utm_source=articles_about_DockerDeep&utm_medium=link&utm_campaign=DockerDeeplinux
【編者按】Docker是PaaS供應商dotCloud開源的一個基於LXC 的高級容器引擎,源代碼託管在 GitHub 上,
基於Go語言開發並聽從Apache
2.0協議開源。Docker提供了一種在安全、可重複的環境中自動部署軟件的方式,它的出現拉開了基於雲計算平臺發佈產品方式的變革序幕。爲了更好的促
進Docker在國內的發展以及傳播,咱們決定開設《深刻淺出Docker》
專欄,邀請Docker相關的佈道師、開發人員、技術專家來說述Docker的各方面內容,讓讀者對Docker有更深刻的瞭解,而且可以積極投入到新技
術的討論和實踐中。另外,歡迎加入InfoQ Docker技術交流×××流Docker的最佳實踐,QQ羣號:124378115。git
2013年2月,前Gluster的CEO Ben Golub和dotCloud的CEO Solomon
Hykes坐在一塊兒聊天時,Solomon談到想把dotCloud內部使用的Container容器技術單獨拿出來開源,而後圍繞這個技術開一家新公司
提供技術支持。28歲的Solomon在使用python開發dotCloud的PaaS雲時發現,使用 LXC(Linux Container)
技術能夠打破產品發佈過程當中應用開發工程師和系統工程師二者之間沒法輕鬆協做發佈產品的難題。這個Container容器技術能夠把開發者從平常部署應用
的繁雜工做中解脫出來,讓開發者能專心寫好程序;從系統工程師的角度來看也是同樣,他們迫切須要從各類混亂的部署文檔中解脫出來,讓系統工程師專一在應用
的水平擴展、穩定發佈的解決方案上。他們越深刻交談,越以爲這是一次雲技術的變革,緊接着在2013年3月Docker
0.1發佈,拉開了基於雲計算平臺發佈產品方式的變革序幕。github
Docker 是 Docker.Inc 公司開源的一個基於 LXC技術之上構建的Container容器引擎, 源代碼託
管在 GitHub 上, 基於Go語言並聽從Apache2.0協議開源。 Docker在2014年6月召開DockerConf
2014技術大會吸引了IBM、Google、RedHat等業界知名公司的關注和技術支持,不管是從 GitHub
上的代碼活躍度,仍是Redhat宣佈在RHEL7中正式支持Docker, 都給業界一個信號,這是一項創新型的技術解決方案。 就連 Google 公司的 Compute Engine 也支持 docker 在其之上運行, 國內「BAT」先鋒企業百度Baidu App Engine(BAE)平臺也是以Docker做爲其PaaS雲基礎。docker
Docker產生的目的就是爲了解決如下問題:
數據庫
1) 環境管理複雜:
從各類OS到各類中間件再到各類App,一款產品可以成功發佈,做爲開發者須要關心的東西太多,且難於管理,這個問題在軟件行業中廣泛存在並須要直接面
對。Docker能夠簡化部署多種應用實例工做,好比Web應用、後臺應用、數據庫應用、大數據應用好比Hadoop集羣、消息隊列等等均可以打包成一個
Image部署。如圖所示:安全
2) 雲計算時代的到來: AWS的成功, 引導開發者將應用轉移到雲上, 解決了硬件管理的問題,然而軟件配置和管理相關的問題依然存在 (AWS cloudformation是這個方向的業界標準, 樣例模板可參考這裏)。Docker的出現正好能幫助軟件開發者開闊思路,嘗試新的軟件管理方法來解決這個問題。ruby
3) 虛擬化手段的變化:
雲時代採用標配硬件來下降成本,採用虛擬化手段來知足用戶按需分配的資源需求以及保證可用性和隔離性。然而不管是KVM仍是Xen,在 Docker
看來都在浪費資源,由於用戶須要的是高效運行環境而非OS, GuestOS既浪費資源又難於管理, 更加輕量級的LXC更加靈活和快速。如圖所示:
4) LXC的便攜性: LXC在 Linux 2.6 的 Kernel
裏就已經存在了,可是其設計之初並不是爲雲計算考慮的,缺乏標準化的描述手段和容器的可便攜性,決定其構建出的環境難於分發和標準化管理(相對於KVM之類
p_w_picpath和snapshot的概念)。Docker就在這個問題上作出了實質性的創新方法。
以Fedora 20做爲主機爲例,直接安裝docker-io:
$ sudo yum -y install docker-io
啓動docker後臺Daemon:
$ sudo systemctl start docker
跑咱們第一個Hello World容器:
$ sudo docker run -i -t fedora /bin/echo hello world Hello world
能夠看到在運行命令行後的下一行會打印出經典的Hello World字符串。
Docker核心是一個操做系統級虛擬化方法, 理解起來可能並不像VM那樣直觀。咱們從虛擬化方法的四個方面:隔離性、可配額/可度量、便攜性、安全性來詳細介紹Docker的技術細節。
每一個用戶實例之間相互隔離, 互不影響。 通常的硬件虛擬化方法給出的方法是VM,而LXC給出的方法是container,更細一點講就是kernel namespace。其中pid、net、ipc、mnt、uts、user等namespace將container的進程、網絡、消息、文件系統、UTS("UNIX Time-sharing System")和用戶空間隔離開。
1) pid namespace
不一樣用戶的進程就是經過pid namespace隔離開的,且不一樣 namespace
中能夠有相同pid。全部的LXC進程在docker中的父進程爲docker進程,每一個lxc進程具備不一樣的namespace。同時因爲容許嵌套,因
此能夠很方便的實現 Docker in Docker。
2) net namespace
有了 pid namespace, 每一個namespace中的pid可以相互隔離,可是網絡端口仍是共享host的端口。網絡隔離是經過net
namespace實現的, 每一個net namespace有獨立的 network devices, IP addresses, IP
routing tables, /proc/net
目錄。這樣每一個container的網絡就能隔離開來。docker默認採用veth的方式將container中的虛擬網卡同host上的一個
docker bridge: docker0鏈接在一塊兒。
3) ipc namespace
container中進程交互仍是採用linux常見的進程間交互方法(interprocess communication – IPC),
包括常見的信號量、消息隊列和共享內存。然而同 VM 不一樣的是,container 的進程間交互實際上仍是host上具備相同pid
namespace中的進程間交互,所以須要在IPC資源申請時加入namespace信息 – 每一個IPC資源有一個惟一的 32 位 ID。
4) mnt namespace
相似chroot,將一個進程放到一個特定的目錄執行。mnt namespace容許不一樣namespace的進程看到的文件結構不一樣,這樣每一個
namespace
中的進程所看到的文件目錄就被隔離開了。同chroot不一樣,每一個namespace中的container在/proc/mounts的信息只包含所在
namespace的mount point。
5) uts namespace
UTS("UNIX Time-sharing System") namespace容許每一個container擁有獨立的hostname和domain name, 使其在網絡上能夠被視做一個獨立的節點而非Host上的一個進程。
6) user namespace
每一個container能夠有不一樣的 user 和 group id, 也就是說能夠在container內部用container內部的用戶執行程序而非Host上的用戶。
cgroups 實現了對資源的配額和度量。 cgroups 的使用很是簡單,提供相似文件的接口,在
/cgroup目錄下新建一個文件夾便可新建一個group,在此文件夾中新建task文件,並將pid寫入該文件,便可實現對該進程的資源控制。
groups能夠限制blkio、cpu、cpuacct、cpuset、devices、freezer、memory、net_cls、ns九大子系
統的資源,如下是每一個子系統的詳細說明:
blkio 這個子系統設置限制每一個塊設備的輸入輸出控制。例如:磁盤,光盤以及usb等等。
cpu 這個子系統使用調度程序爲cgroup任務提供cpu的訪問。
cpuacct 產生cgroup任務的cpu資源報告。
cpuset 若是是多核心的cpu,這個子系統會爲cgroup任務分配單獨的cpu和內存。
devices 容許或拒絕cgroup任務對設備的訪問。
freezer 暫停和恢復cgroup任務。
memory 設置每一個cgroup的內存限制以及產生內存資源報告。
net_cls 標記每一個網絡包以供cgroup方便使用。
ns 名稱空間子系統。
以上九個子系統之間也存在着必定的關係.詳情請參閱官方文檔。
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 p_w_picpath 不變的基礎上容許用戶在其上進行一些寫操做。Docker 在 AUFS 上構建的
container p_w_picpath 也正是如此,接下來咱們從啓動 container 中的 linux 爲例來介紹 docker
對AUFS特性的運用。
典型的啓動Linux運行須要兩個FS: bootfs + rootfs:
bootfs (boot file system) 主要包含 bootloader 和 kernel,
bootloader主要是引導加載kernel, 當boot成功後 kernel 被加載到內存中後 bootfs就被umount了.
rootfs (root file system) 包含的就是典型 Linux 系統中的 /dev, /proc,/bin, /etc
等標準目錄和文件。
對於不一樣的linux發行版, bootfs基本是一致的, 但rootfs會有差異, 所以不一樣的發行版能夠公用bootfs 以下圖:
典型的Linux在啓動後,首先將 rootfs 設置爲 readonly, 進行一系列檢查, 而後將其切換爲 "readwrite"
供用戶使用。在Docker中,初始化時也是將 rootfs 以readonly方式加載並檢查,然而接下來利用 union mount
的方式將一個 readwrite 文件系統掛載在 readonly 的rootfs之上,而且容許再次將下層的 FS(file system)
設定爲readonly 而且向上疊加, 這樣一組readonly和一個writeable的結構構成一個container的運行時態,
每個FS被稱做一個FS層。以下圖:
得益於AUFS的特性, 每個對readonly層文件/目錄的修改都只會存在於上層的writeable層中。這樣因爲不存在競爭, 多個container能夠共享readonly的FS層。 因此Docker將readonly的FS層稱做 "p_w_picpath" – 對於container而言整個rootfs都是read-write的,但事實上全部的修改都寫入最上層的writeable層中, p_w_picpath不保存用戶狀態,只用於模板、新建和複製使用。
上層的p_w_picpath依賴下層的p_w_picpath,所以Docker中把下層的p_w_picpath稱做父p_w_picpath,沒有父p_w_picpath的p_w_picpath稱做base
p_w_picpath。所以想要從一個p_w_picpath啓動一個container,Docker會先加載這個p_w_picpath和依賴的父p_w_picpaths以及base
p_w_picpath,用戶的進程運行在writeable的layer中。全部parent p_w_picpath中的數據信息以及
ID、網絡和lxc管理的資源限制等具體container的配置,構成一個Docker概念上的container。以下圖:
安全永遠是相對的,這裏有三個方面能夠考慮Docker的安全特性:
由kernel namespaces和cgroups實現的Linux系統固有的安全標準;
Docker Deamon的安全接口;
Linux自己的安全加固解決方案,類如AppArmor, SELinux;
因爲安全屬於很是具體的技術,這裏不在贅述,請直接參閱Docker官方文檔。
咱們再來看看Docker社區還有哪些子項目值得咱們去好好研究和學習。基於這個目的,我把有趣的核心項目給你們羅列出來,讓熱心的讀者能快速跟進本身感興趣的項目:
Libswarm,是Solomon Hykes (Docker的CTO) 在DockerCon
2014峯會上向社區介紹的新「樂高積木」工具:
它是用來統一分佈式系統的網絡接口的API。Libswarm要解決的問題是,基於Docker構建的分佈式應用已經催生了多個基於Docker的服務發
現(Serivce Discovery)項目,例如etcd, fleet, geard, mesos, shipyard,
serf等等,每一套解決方案都有本身的通信協議和使用方法,使用其中的任意一款都會侷限在某一個特定的技術範圍內。因此Docker的CTO就想用
libswarm暴露出通用的API接口給分佈式系統使用,打破既定的協議限制。目前項目還在早期發展階段,值得參與。
Libchan,是一個底層的網絡庫,爲上層 Libswarm
提供支持。至關於給Docker加上了ZeroMQ或RabbitMQ,這裏本身實現網絡庫的好處是對Docker作了特別優化,更加輕量級。通常開發者
不會直接用到它,你們更多的仍是使用Libswarm來和容器交互。喜歡底層實現的網絡工程師可能對此感興趣,不妨一看。
Libcontainer,Docker技術的核心部分,單獨列出來也是由於這一塊的功能相對獨立,功能代碼的迭代升級很是快。想了解Docker最新的支持特性應該多關注這個模塊。
Docker社區一直在面對技術挑戰,從容地給出本身的解決方案。雲計算髮展至今,有不少重要的問題沒有獲得妥善解決,Docker正在嘗試讓主流
廠商接受並應用它。至此,以上Docker技術的預覽到此告一段落,筆者也但願讀者能結合本身的實際狀況,嘗試使用Docker技術。由於只有在親自體會
的基礎之上,像Docker這樣的雲技術纔會產生更大的價值。
肖德時, Red Hat Engineering Service/HSS 內部工具組Team
Leader,Nodejs開源項目nodejs-cantas Lead Developer。擅長企業內部工具的設計以及實現。開源課程Rails
Starter的發起人。rubygem:
lazy_high_charts的Maintainer。twitter帳號:xds2000,郵箱:xiaods@gmail.com
感謝郭蕾對本文的審校。