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發佈,拉開了基於雲計算平臺發佈產品方式的變革序幕。html
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雲基礎。python
Docker產生的目的就是爲了解決如下問題:linux
1) 環境管理複雜: 從各類OS到各類中間件再到各類App,一款產品可以成功發佈,做爲開發者須要關心的東西太多,且難於管理,這個問題在軟件行業中廣泛存在並須要直接面對。Docker能夠簡化部署多種應用實例工做,好比Web應用、後臺應用、數據庫應用、大數據應用好比Hadoop集羣、消息隊列等等均可以打包成一個Image部署。如圖所示:git
2) 雲計算時代的到來: AWS的成功, 引導開發者將應用轉移到雲上, 解決了硬件管理的問題,然而軟件配置和管理相關的問題依然存在 (AWS cloudformation是這個方向的業界標準, 樣例模板可參考這裏)。Docker的出現正好能幫助軟件開發者開闊思路,嘗試新的軟件管理方法來解決這個問題。github
3) 虛擬化手段的變化: 雲時代採用標配硬件來下降成本,採用虛擬化手段來知足用戶按需分配的資源需求以及保證可用性和隔離性。然而不管是KVM仍是Xen,在 Docker 看來都在浪費資源,由於用戶須要的是高效運行環境而非OS, GuestOS既浪費資源又難於管理, 更加輕量級的LXC更加靈活和快速。如圖所示:docker
4) LXC的便攜性: LXC在 Linux 2.6 的 Kernel 裏就已經存在了,可是其設計之初並不是爲雲計算考慮的,缺乏標準化的描述手段和容器的可便攜性,決定其構建出的環境難於分發和標準化管理(相對於KVM之類image和snapshot的概念)。Docker就在這個問題上作出了實質性的創新方法。數據庫
以Fedora 20做爲主機爲例,直接安裝docker-io:安全
$ sudo yum -y install docker-io
啓動docker後臺Daemon:網絡
$ sudo systemctl start docker
跑咱們第一個Hello World容器:dom
$ 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九大子系統的資源,如下是每一個子系統的詳細說明:
以上九個子系統之間也存在着必定的關係.詳情請參閱官方文檔。
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 在 AUFS 上構建的 container image 也正是如此,接下來咱們從啓動 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層稱做 "image" - 對於container而言整個rootfs都是read-write的,但事實上全部的修改都寫入最上層的writeable層中, image不保存用戶狀態,只用於模板、新建和複製使用。
上層的image依賴下層的image,所以Docker中把下層的image稱做父image,沒有父image的image稱做base image。所以想要從一個image啓動一個container,Docker會先加載這個image和依賴的父images以及base image,用戶的進程運行在writeable的layer中。全部parent image中的數據信息以及 ID、網絡和lxc管理的資源限制等具體container的配置,構成一個Docker概念上的container。以下圖:
安全永遠是相對的,這裏有三個方面能夠考慮Docker的安全特性:
因爲安全屬於很是具體的技術,這裏不在贅述,請直接參閱Docker官方文檔。
咱們再來看看Docker社區還有哪些子項目值得咱們去好好研究和學習。基於這個目的,我把有趣的核心項目給你們羅列出來,讓熱心的讀者能快速跟進本身感興趣的項目:
Docker社區一直在面對技術挑戰,從容地給出本身的解決方案。雲計算髮展至今,有不少重要的問題沒有獲得妥善解決,Docker正在嘗試讓主流廠商接受並應用它。至此,以上Docker技術的預覽到此告一段落,筆者也但願讀者能結合本身的實際狀況,嘗試使用Docker技術。由於只有在親自體會的基礎之上,像Docker這樣的雲技術纔會產生更大的價值。