1. 程式人生 > >Docker的體系結構

Docker的體系結構

體系結構 docker

docker使用C/S 架構,docker daemon 作為 server 端接受 client 的請求,並處理(創建、運行、分發容器),他們可以運行在一個機器上,也通過 socket或者 RESTful API 通信

技術分享

Docker daemon 一般在宿主主機後臺運行。

Docker client以系統命令的形式存在,用戶用docker命令來跟docker daemon 交互。

Docker 守護進程Docker daemon

如上圖所示,Docker 守護進程運行在一臺主機上。用戶並不直接和守護進程進行交互,而是通過 Docker 客戶端間接和其通信。

Docker 客戶端Docker client

Docker 客戶端,實際上是docker的二進制程序,是用戶與 Docker 交互方式。它接收用戶指令並且與背後的 Docker 守護進程通信。

技術分享

Docker 內部

要理解 Docker 內部構建,需要理解以下三種部件:

Docker 鏡像 - Docker images

Docker 倉庫 - Docker registeries

Docker 容器 - Docker containers

Docker 鏡像

Docker 鏡像是 Docker 容器運行時的只讀模板,鏡像可以用來創建 Docker 容器。每一個鏡像由一系列的層 (layers) 組成。Docker 使用UnionFS(聯合文件系統)來將這些層聯合到單獨的鏡像中。UnionFS允許獨立文件系統中的文件和文件夾(稱之為分支)被透明覆蓋,形成一個單獨連貫的文件系統。正因為有了這些層的存在,

Docker 是如此的輕量。當你改變了一個 Docker 鏡像,比如升級到某個程序到新的版本,一個新的層會被創建。因此,不用替換整個原先的鏡像或者重新建立(在使用虛擬機的時候你可能會這麽做),只是一個新的層被添加或升級了。現在你不用重新發布整個鏡像,只需要升級,層使得分發 Docker 鏡像變得簡單和快速。

每個docker都有很多層次構成,docker使用 union file systems 將這些不同的層結合到一個image 中去。

例如:centos鏡像中安裝nginx,就成了nginx鏡像,其實在此時Docker鏡像的層級概念就體現出來了。底層一個centos操作系統鏡像,上面疊加一個ngnx層,就完成了一個nginx鏡像的構建。層級概念就不難理解,此時我們一般centos操作系統鏡像稱為nginx鏡像層的父鏡像。


技術分享

Docker 倉庫

Docker 倉庫用來保存鏡像,可以理解為代碼控制中的代碼倉庫。同樣的,Docker 倉庫也有公有和私有的概念。公有的 Docker 倉庫名字是 Docker Hub。Docker Hub 提供了龐大的鏡像集合供使用。這些鏡像可以是自己創建,或者在別人的鏡像基礎上創建。

倉庫是集中存放鏡像文件的場所。有時候會把倉庫和倉庫註冊服務器(Registry)混為一談,並不嚴格區分。實際上,倉庫註冊服務器上往往存放著多個倉庫,每個倉庫中又包含了多個鏡像,每個鏡像有不同的標簽(tag)。

倉庫分為公開倉庫(Public)和私有倉庫(Private)兩種形式。

最大的公開倉庫是 Docker Hub,存放了數量龐大的鏡像供用戶下載。國內的公開倉庫包括 Docker Pool等,可以提供大陸用戶更穩定快速的訪問。

當然,用戶也可以在本地網絡內創建一個私有倉庫。

當用戶創建了自己的鏡像之後就可以使用push命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上pull下來就可以了。

*註:Docker 倉庫的概念跟Git類似,註冊服務器可以理解為 GitHub 這樣的托管服務。

Docker 容器

Docker 利用容器來運行應用,一個Docker容器包含了所有的某個應用運行所需要的環境。每一個 Docker 容器都是從 Docker 鏡像創建的。Docker 容器可以運行、開始、停止、移動和刪除。每一個 Docker 容器都是獨立和安全的應用平臺。

容器是從鏡像創建的運行實例。它可以被啟動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平臺。

可以把容器看做是一個簡易版的 Linux 環境(包括root用戶權限、進程空間、用戶空間和網絡空間等)和運行在其中的應用程序。

*註:鏡像是只讀的,容器在啟動的時候創建一層可寫層作為最上層。

技術分享

與虛擬機相比,容器有一個很大的差異,它們被設計用來運行"單進程",無法很好地模擬一個完整的環境。Docker設計者極力推崇“一個容器一個進程的方式”,如果你要選擇在一個容器中運行多個進程,那唯一情況是:出於調試目的。

容器是設計來運行一個應用的,而非一臺機器。你可能會把容器當虛擬機用,但你將失去很多的靈活性,因為Docker提供了用於分離應用與數據的工具,使得你可以快捷地更新運行中的代碼/系統,而不影響數據。

Docker 從 0.9 版本開始使用 libcontainer 替代 lxc,libcontainer 和 Linux 系統的交互圖如下:

技術分享

Docker 底層技術

docker底層的 2 個核心技術分別是 Namespaces Control groups

Namespaces用來隔離各個容器

1)pid namespace

不同容器的進程就是通過pid namespace 隔離開的,且不同 namespace 中可以有相同pid。所有的LXC進程在docker中的父進程為docker進程,每個lxc進程具有不同的 namespace

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),包括常見的信號量、消息隊列和共享內存。container 的進程間交互實際上還是host 上具有相同ipc namespace 中的進程間交互。

4) mnt namespace

類似chroot,將一個進程放到一個特定的目錄執行。mnt namespace 允許不同 namespace 的進程看到的文件結構不同,這樣每個 namespace 中的進程所看到的文件目錄就被隔離開了。container裏頭,看到的文件系統,就是一個完整的linux系統,有/etc/lib 等,通過chroot實現。

5) uts namespace

UTS("UNIX Time-sharing System") namespace 允許每個 container 擁有獨立的 hostname domain name, 使其在網絡上可以被視作一個獨立的節點而非 Host 上的一個進程。

6) user namespace

每個 container 可以有不同的 user group id, 也就是說可以在 container 內部用 container 內部的用戶執行程序而非 Host 上的用戶。

有了以上 6 namespace 從進程、網絡、IPC、文件系統、UTS和用戶角度的隔離,一個 container 就可以對外展現出一個獨立計算機的能力,並且不同 container OS 層面實現了隔離。然而不同 namespace 之間資源還是相互競爭的,仍然需要類似ulimit來管理每個 container 所能使用的資源 - -cgroup

cgroupsControl groups實現了對資源的配額和度量。


本文出自 “duyuheng” 博客,謝絕轉載!

Docker的體系結構