【編者的話】本文來自 Docker 的官方文檔,詳細介紹了 Docker 的體系結構、重要概念、內部工做機理等內容,推薦不瞭解 Docker 內部原理的同窗閱讀。python
Docker 是一個用於開發、交付和運行應用的開放平臺,Docker 設計用來更快的交付你的應用程序。Docker 能夠將你的應用程序和基礎設施層隔離,而且還能夠將你的基礎設施看成程序同樣進行管理。Docker 能夠幫助你更塊地打包你代碼、測試以及部署,而且也能夠減小從編寫代碼到部署運行代碼的週期。linux
Docker 將一個輕量級的容器虛擬化平臺和一組標準工做流程、工具進行集成,來幫助你方便地管理和部署應用。docker
核心是,Docker 提供了一種在安全隔離的容器中運行近乎全部應用的方式,這種隔離性和安全性容許你在同一主機上同時運行多個容器,而容器的這種輕量級特性,意味着你能夠節省更多的硬件資源,由於你沒必要消耗運行 hypervisor 所須要的額外負載。ubuntu
基於容器虛擬化的工具或者平臺能夠爲你提供以下幫助:安全
Docker是開發過程當中較爲理想的助手,它容許你在包含了你的應用和服務的本地容器中進行開發,而後幫你完成集成和部署。bash
例如,你的開發人員能夠在本地編寫代碼而後經過Docker與其餘同事共享,當他們完成了各自的開發任務後,能夠將他們的代碼推送到一個測試的環境中進行測試,完成測試後即可以將相應的Docker鏡像部署到生產環境中。服務器
Docker這種基於容器的平臺具備高度的便攜性,它能夠無縫地運行於開發者的本地主機、數據中心其它的物理機或虛擬機、或者雲端。網絡
Docker的便攜性和其自然的輕量特性易於實現動態地負載管理,你能夠利用Docker快速地增減應用和服務的部署規模,Docker的速度保證了這種規模的調整近乎實時。架構
因爲Docker輕量而且快速,所以相對於基於Hypervisor的虛擬機的部署方式,Docker提供了一種更可行和划算的替代方案,這對於高密度部署環境尤爲有用,例如在構建私有云或PaaS。固然,當你想在有限的資源裏部署更多的應用時,Docker對於中小型的部署也很是有用。app
Docker主要包括兩個組件:
注:Docker在Apache 2.0開源協議下進行受權。
Docker是Client/Server的架構,Docker客戶端與Docker daemon進行交互,daemon負責構建、運行和發佈Docker容器。客戶端能夠和服務端運行在同一個系統中,也能夠鏈接遠程的daemon。Docker的客戶端的daemon經過RESTful API進行socket通訊。
[
就像上圖所示,Docker守護進程(daemon)在主機上運行,用戶不能直接和守護進程打交道,可是能夠經過Docker客戶端與其進行交互。
Docker客戶端——docker
二進制文件的功能之一——是Docker的初始用戶界面,它接收用戶的命令並反饋,而且與Docker的守護進行交互。
理解Docker的內部機制,你須要明白以下三個組件:
Docker鏡像是一個只讀的模板。例如,一個鏡像能夠包含安裝了Apache Web服務應用的Ubuntu操做系統。鏡像能夠用來建立Docker容器。Docker提供了構建新鏡像或升級原有鏡像的較爲便利的方式,或者你也能夠下載別人已經建立好的鏡像。Docker鏡像是Docker的構建組件。
Docker註冊中心用於上傳和下載鏡像,分爲公共註冊中心和私有註冊中心兩種。公共註冊中心爲Docker Hub,它提供了大量的現成鏡像,你能夠構建本身的鏡像並上傳到上面,也能夠在上面下載別人構建的鏡像。Docker註冊中心是Docker的發佈組件。
Docker容器就像是一個文件夾,它包含了一個應用程序運行所須要的全部內容。每一個容器都是基於Docker鏡像構建。咱們能夠運行、開始、中止、遷移或者是刪除Docker容器。每一個容器均是一個隔離的、安全的應用平臺。Docker容器是Docker的運行組件。
至此,咱們已經知道了:
那咱們看看 Docker 是怎麼將這些元素組合在一塊兒工做的。
咱們已經知道Docker鏡像實質上是一些用於加載Docker容器的只讀模板,每一個鏡像包括不少層。Docker利用union file systems將這些層組合爲一個鏡像。Union file systems容許相互隔離的文件或目錄透明的疊加在一塊兒,而呈現爲一個統一的文件系統。
Docker如此輕量化的緣由也是因爲這些層的存在。當你對一個Docker鏡像進行修改時——例如將一個應用升級爲一個新的版本——會構建一個新的層,所以,與虛擬機的替換整個鏡像或徹底構建的方式不一樣,Docker僅對相關的層進行添加或升級。因此你僅須要發佈鏡像的更新部分而沒必要發佈整個鏡像,這種方式使得鏡像的發佈更加快速和簡單。
每一個鏡像始於一個基礎鏡像,例如:ubuntu
即是一個基礎的Ubuntu鏡像,fedora
是一個基礎的Fedora鏡像。你也能夠將你本身製做的鏡像做爲基礎鏡像,例如你能夠將一個Apache鏡像做爲一個Web應用的基礎鏡像。
注意:Docker通常從Docker Hub上獲取基礎鏡像。Docker鏡像從這些基礎鏡像中按照一系列的步驟進行製做,咱們稱這些步驟爲指令,每一個指令在你的鏡像中建立一個新的層,指令包括如下行爲:
這些指令存儲在Dockerfile
中,Docker在構建鏡像過程當中讀取這個Dockerfile
,運行裏面的指令並返回最終的鏡像。
Docker註冊中心是Docker鏡像的存儲中心,當你構建完一個鏡像後即可以將其推送到Docker Hub或你本身的註冊中心。
利用Docker客戶端,你能夠搜索已經發布的鏡像,而後將其拉取到你的Docker主機上,以便於基於這些鏡像構建容器。
Docker Hub爲鏡像提供了公共的和私有的存儲空間。公共的存儲空間任何人都可以在上面搜索和下載,私有存儲空間僅對你本人或你的團隊開放搜索以及拉取下載,你能夠經過這裏註冊一個私有的存儲空間。
一個容器包括操做系統、用戶添加的文件以及相關的元數據。咱們知道,每一個容器都是從鏡像中構建出來的,這個鏡像告訴Docker容器用到什麼資源、當容器加載時啓動哪一個進程以及容器啓動時的其它配置。Docker鏡像是隻讀的,當Docker從一個鏡像運行一個容器時,它會在鏡像的上層添加一個用於運行應用的可讀寫的層(利用的就是上文提到的union file system)。
不論是經過Docker命令仍是API調用的方式,Docker客戶端都會通知Docker的守護進程運行一個容器。
sudo docker run -i -t ubuntu /bin/bash
咱們來看一下這個命令,Docker客戶端利用docker
命令並結合run
選項來啓動一個容器,一個最小配置的Docker客戶端運行一個容器須要告訴Docker守護進程如下事項:
ubuntu
——一個基礎的Ubuntu鏡像;/bin/bash
——在容器中啓動一個Bash Shell。那麼咱們看看運行上述命令時到底發生了什麼?
按照順序,Docker依次幹了以下事情:
ubuntu
鏡像 : Docker首先檢查一下ubuntu
鏡像在本地服務器上存不存在,若是不存在,則自動從Docker Hub中下載,若是已經存在則直接利用這個鏡像來啓動一個新的容器。如今你已經運行了一個容器,這樣你即可以管理你的容器、與應用程序進行交互,當運行結束是中止或者刪除你的容器。
Docker是用Go語言實現的,用到了一些Linux內核的特性實現上述功能。
Docker在爲容器提供一個隔離的工做空間時,用到了命名空間
的技術,當你運行一個容器時,Docker會爲此容器建立一組命名空間。
這樣即可以提供一個隔離的層:每一個容器運行在本身的命名空間中,而外部不能訪問這個層。
Docker用到的一些命名空間有:
pid
命名空間: 用於隔離進程(PID:Process ID);net
命名空間: 用於管理網絡;ipc
命名空間: 用於訪問IPC資源(IPC:InterProcess Communication);mnt
命名空間: 用於管理掛載點(MNT:Mount);uts
命名空間: 用於隔離內核和版本標識(UTS:Unix Timesharing System)。Docker還用到了另一項技術叫cgroups
或者叫控制組(control groups)。實現程序運行環境的隔離的關鍵在於使這些程序只用到它們須要的資源,這就可以保證這些容器是主機服務環境小社會中的好市民。控制組容許Docker在不一樣的容器之間共享硬件資源,須要時添加一些限制和約束,例如限制一個容器最大訪問內存量。
統一文件系統或者說是UnionFS,是建立層的時候用到的文件系統,使文件系統很是輕量和快速。Docker使用統一文件系統爲容器構建blocks,Docker可使用幾種不一樣的文件系統:AUFS、btrfs、vfs以及DeviceMapper。
Docker容器將這些組件合併在一塊兒,咱們稱之爲容器格式,容器的缺省格式稱爲libcontainer
。Docker還支持利用LXC技術的傳統Linux容器格式,將來還將會支持其它的容器格式,例如:與BSD Jails或者Solaris Zones實現整合。
原文連接:Understanding Docker(翻譯:deerlux 校對:李穎傑)
譯者介紹:deerlux@163.com,現就任於一家軍工科研機構,深度的技術控、Linux控、python控。