一文帶你讀懂什麼是docker

一 簡介

1、瞭解Docker的前生LXC

LXC爲Linux Container的簡寫。一種輕量級的內核虛擬化技術,隔離進程和資源。

Linux Container有點像chroot,提供了一個擁有自己進程和網絡空間的虛擬環境,但又有別於虛擬機,因爲lxc是一種操作系統層次的虛擬化。

2、LXC與docker什麼關係?

docker並不是LXC替代品,docker底層使用LXC來實現,LXC將linux進程沙盒化,使得進程之間相互隔離,並且能夠控制各進程的資源分配。

在LXC的基礎之上,docker提供了一系列更強大的功能。

3、什麼是docker

docker是一個開源的應用容器引擎,基於go語言開發並遵從Apache2.0協議開源。

docker可以讓開發者打包他們的應用到一個可移植的容器中,然後發佈到任何linux機器上。

容器之間使用沙箱機制,相互沒有任何接口(類iphone的app),並且容器開銷極低。

4、與傳統VM特性對比:

  • Docker 容器很快,啓動和停止可以在秒級實現,相比傳統的虛擬機方式要快得多。

  • Docker 容器對系統資源需求很少,一臺主機上可以同時運行數千個Docker容器。

  • Docker 通過類似Git的操作來方便用戶獲取、分發和更新應用鏡像,指令簡明,學習成本較低。

  • Docker 通過Dockerfile配置文件來支持靈活的自動化創建和部署機制,提高工作效率。

  • Docker 容器除了運行其中的應用之外,基本不消耗額外的系統資源,保證應用性能的同時,儘量減小系統開銷。

  • Docker 利用Linux系統上的多種防護機制實現了嚴格可靠的隔離。從1.3版本開始,Docker引入了安全選項和鏡像簽名機制,極大地提高了Docker的安全性。

5、相關概念:

  • 鏡像和容器(containers)


通過鏡像來啓動一個容器,一個鏡像是一個可執行的包,其中包括運行應用程序所需要的所有內容(包含代碼,運行時間,庫、環境變量和配置文件等)。

容器是鏡像的運行實例,當被運行時有鏡像狀態和用戶進程,可以使用docker ps 查看。

  • 容器和虛擬機

容器是在linux主機運行,並與其他容器共享主機的內核,它運行一個獨立的進程,不佔用其他任何內存,非常輕量。

虛擬機運行的是一個完成的操作系統,通過虛擬機管理程序對主機資源進行虛擬訪問,相比之下需要的資源更多。

 

6、docker版本

Docker Community Edition(CE)社區版

Docker  Enterprise Edition(EE) 商業版

7、docker和openstack的幾項對比

 

8、容器在內核中支持2種重要技術

docker本質就是宿主機的一個進程,docker通過namespace實現資源隔離,通過cgroup實現資源限制,通過寫時複製技術(copy-on-write)實現了高效的文件操作(類似虛擬機的磁盤比如分配500g並不是實際佔用物理磁盤500g)

1)namespaces 名稱空間

 

 

 2)control Group 控制組

cgroup的特點是:      

  • cgroup的api以一個僞文件系統的實現方式,用戶的程序可以通過文件系統實現cgroup的組件管理

  • cgroup的組件管理操作單元可以細粒度到線程級別,另外用戶可以創建和銷燬cgroup,從而實現資源載分配和再利用

  • 所有資源管理的功能都以子系統的方式實現,接口統一子任務創建之初與其父任務處於同一個cgroup的控制組

9、瞭解docker三個重要概念

1)image鏡像

docker鏡像就是一個只讀模板,比如,一個鏡像可以包含一個完整的centos,裏面僅安裝apache或用戶的其他應用,鏡像可以用來創建docker容器,另外docker提供了一個很簡單的機制來創建鏡像或者更新現有的鏡像,用戶甚至可以直接從其他人那裏下載一個已經做好的鏡像來直接使用

2)container容器

docker利用容器來運行應用,容器是從鏡像創建的運行實例,它可以被啓動,開始、停止、刪除、每個容器都是互相隔離的,保證安全的平臺,可以吧容器看做是要給簡易版的linux環境(包括root用戶權限、鏡像空間、用戶空間和網絡空間等)和運行在其中的應用程序

 

3)repostory倉庫

倉庫是集中存儲鏡像文件的地方,倉庫分爲兩種,公有倉庫 私有倉庫,最大的公有倉庫是docker Hub,存放了數量龐大的鏡像供用戶下載。這裏倉庫的概念與Git類似,registry可以理解爲github這樣的託管服務。

10、docker的主要用途

實現應用的封裝、部署、運行的生命週期管理只要在glibc的環境下,都可以運行。

運維生成環境中:docker化。

  • 發佈服務不用擔心服務器的運行環境,所有的服務器都是自動分配docker,自動部署,自動安裝,自動運行

  • 再不用擔心其他服務引擎的磁盤問題,cpu問題,系統問題了

  • 資源利用更出色

  • 自動遷移,可以製作鏡像,遷移使用自定義的鏡像即可遷移,不會出現什麼問題

  • 管理更加方便了

11、docker改變了什麼

  • 面向產品:產品交付

  • 面向開發:簡化環境配置

  • 面向測試:多版本測試

  • 面向運維:環境一致性

  • 面向架構:自動化擴容(微服務)

二 docker架構

1、總體架構

  • distribution 負責與docker registry交互,上傳鏡像以及v2 registry 有關的源數據

  • registry負責docker registry有關的身份認證、鏡像查找、鏡像驗證以及管理registry mirror等交互操作

  • image 負責與鏡像源數據有關的存儲、查找,鏡像層的索引、查找以及鏡像tar包有關的導入、導出操作

  • reference負責存儲本地所有鏡像的repository和tag名,並維護與鏡像id之間的映射關係

  • layer模塊負責與鏡像層和容器層源數據有關的增刪改查,並負責將鏡像層的增刪改查映射到實際存儲鏡像層文件的graphdriver模塊

  • graghdriver是所有與容器鏡像相關操作的執行者

2、docker架構2

如果覺得上面架構圖比較亂可以看這個架構:

從上圖不難看出,用戶是使用Docker Client與Docker Daemon建立通信,併發送請求給後者。

而Docker Daemon作爲Docker架構中的主體部分,首先提供Server的功能使其可以接受Docker Client的請求;而後Engine執行Docker內部的一系列工作,每一項工作都是以一個Job的形式的存在。

Job的運行過程中,當需要容器鏡像時,則從Docker Registry中下載鏡像,並通過鏡像管理驅動graphdriver將下載鏡像以Graph的形式存儲;當需要爲Docker創建網絡環境時,通過網絡管理驅動networkdriver創建並配置Docker容器網絡環境;當需要限制Docker容器運行資源或執行用戶指令等操作時,則通過execdriver來完成。

而libcontainer是一項獨立的容器管理包,networkdriver以及execdriver都是通過libcontainer來實現具體對容器進行的操作。當執行完運行容器的命令後,一個實際的Docker容器就處於運行狀態,該容器擁有獨立的文件系統,獨立並且安全的運行環境等。

3、docker架構3

再來看看另外一個架構,這個個架構就簡單清晰指明瞭server/client交互,容器和鏡像、數據之間的一些聯繫。

這個架構圖更加清晰了架構

docker daemon就是docker的守護進程即server端,可以是遠程的,也可以是本地的,這個不是C/S架構嗎,客戶端Docker client 是通過rest api進行通信。

docker cli 用來管理容器和鏡像,客戶端提供一個只讀鏡像,然後通過鏡像可以創建多個容器,這些容器可以只是一個RFS(Root file system根文件系統),也可以ishi一個包含了用戶應用的RFS,容器再docker client中只是要給進程,兩個進程之間互不可見。

用戶不能與server直接交互,但可以通過與容器這個橋樑來交互,由於是操作系統級別的虛擬技術,中間的損耗幾乎可以不計。

三、docker架構2各個模塊的功能(待完善)

主要模塊:Docker Client、Docker Daemon、Docker Registry、Graph、Driver、libcontainer以及Docker container。   

1、docker client

docker client 是docker架構中用戶用來和docker daemon建立通信的客戶端,用戶使用的可執行文件爲docker,通過docker命令行工具可以發起衆多管理container的請求。

docker client可以通過一下三宗方式和docker daemon建立通信:tcp://host:port;unix:path_to_socket;fd://socketfd。,docker client可以通過設置命令行flag參數的形式設置安全傳輸層協議(TLS)的有關參數,保證傳輸的安全性。

docker client發送容器管理請求後,由docker daemon接受並處理請求,當docker client 接收到返回的請求相應並簡單處理後,docker client 一次完整的生命週期就結束了,當需要繼續發送容器管理請求時,用戶必須再次通過docker可以執行文件創建docker client。

2、docker daemon

docker daemon 是docker架構中一個常駐在後臺的系統進程,功能是:接收處理docker client發送的請求。該守護進程在後臺啓動一個server,server負載接受docker client發送的請求;接受請求後,server通過路由與分發調度,找到相應的handler來執行請求。

docker daemon啓動所使用的可執行文件也爲docker,與docker client啓動所使用的可執行文件docker相同,在docker命令執行時,通過傳入的參數來判別docker daemon與docker client。

docker daemon的架構可以分爲:docker server、engine、job。daemon

3、docker server

docker server在docker架構中時專門服務於docker client的server,該server的功能時:接受並調度分發docker client發送的請求,架構圖如下:

    

在Docker的啓動過程中,通過包gorilla/mux(golang的類庫解析),創建了一個mux.Router,提供請求的路由功能。在Golang中,gorilla/mux是一個強大的URL路由器以及調度分發器。該mux.Router中添加了衆多的路由項,每一個路由項由HTTP請求方法(PUT、POST、GET或DELETE)、URL、Handler三部分組成。

若Docker Client通過HTTP的形式訪問Docker Daemon,創建完mux.Router之後,Docker將Server的監聽地址以及mux.Router作爲參數,創建一個httpSrv=http.Server{},最終執行httpSrv.Serve()爲請求服務。

在Server的服務過程中,Server在listener上接受Docker Client的訪問請求,並創建一個全新的goroutine來服務該請求。在goroutine中,首先讀取請求內容,然後做解析工作,接着找到相應的路由項,隨後調用相應的Handler來處理該請求,最後Handler處理完請求之後回覆該請求。

需要注意的是:Docker Server的運行在Docker的啓動過程中,是靠一個名爲」serveapi」的job的運行來完成的。原則上,Docker Server的運行是衆多job中的一個,但是爲了強調Docker Server的重要性以及爲後續job服務的重要特性,將該」serveapi」的job單獨抽離出來分析,理解爲Docker Server。

4、engine

Engine是Docker架構中的運行引擎,同時也Docker運行的核心模塊。它扮演Docker container存儲倉庫的角色,並且通過執行job的方式來操縱管理這些容器。

在Engine數據結構的設計與實現過程中,有一個handler對象。該handler對象存儲的都是關於衆多特定job的handler處理訪問。舉例說明,Engine的handler對象中有一項爲:{「create」: daemon.ContainerCreate,},則說明當名爲」create」的job在運行時,執行的是daemon.ContainerCreate的handler。

5、job

一個Job可以認爲是Docker架構中Engine內部最基本的工作執行單元。Docker可以做的每一項工作,都可以抽象爲一個job。例如:在容器內部運行一個進程,這是一個job;創建一個新的容器,這是一個job,從Internet上下載一個文檔,這是一個job;包括之前在Docker Server部分說過的,創建Server服務於HTTP的API,這也是一個job,等等。

Job的設計者,把Job設計得與Unix進程相仿。比如說:Job有一個名稱,有參數,有環境變量,有標準的輸入輸出,有錯誤處理,有返回狀態等。

6、docker registry

Docker Registry是一個存儲容器鏡像的倉庫。而容器鏡像是在容器被創建時,被加載用來初始化容器的文件架構與目錄。

在Docker的運行過程中,Docker Daemon會與Docker Registry通信,並實現搜索鏡像、下載鏡像、上傳鏡像三個功能,這三個功能對應的job名稱分別爲」search」,」pull」 與 「push」。

其中,在Docker架構中,Docker可以使用公有的Docker Registry,即大家熟知的Docker Hub,如此一來,Docker獲取容器鏡像文件時,必須通過互聯網訪問Docker Hub;同時Docker也允許用戶構建本地私有的Docker Registry,這樣可以保證容器鏡像的獲取在內網完成。

7、Graph

Graph在Docker架構中扮演已下載容器鏡像的保管者,以及已下載容器鏡像之間關係的記錄者。一方面,Graph存儲着本地具有版本信息的文件系統鏡像,另一方面也通過GraphDB記錄着所有文件系統鏡像彼此之間的關係。

Graph的架構如下:

其中,GraphDB是一個構建在SQLite之上的小型圖數據庫,實現了節點的命名以及節點之間關聯關係的記錄。它僅僅實現了大多數圖數據庫所擁有的一個小的子集,但是提供了簡單的接口表示節點之間的關係。

同時在Graph的本地目錄中,關於每一個的容器鏡像,具體存儲的信息有:該容器鏡像的元數據,容器鏡像的大小信息,以及該容器鏡像所代表的具體rootfs。

 

8、driver

Driver是Docker架構中的驅動模塊。通過Driver驅動,Docker可以實現對Docker容器執行環境的定製。由於Docker運行的生命週期中,並非用戶所有的操作都是針對Docker容器的管理,另外還有關於Docker運行信息的獲取,Graph的存儲與記錄等。因此,爲了將Docker容器的管理從Docker Daemon內部業務邏輯中區分開來,設計了Driver層驅動來接管所有這部分請求。

在Docker Driver的實現中,可以分爲以下三類驅動:graphdriver、networkdriver和execdriver。

graphdriver主要用於完成容器鏡像的管理,包括存儲與獲取。即當用戶需要下載指定的容器鏡像時,graphdriver將容器鏡像存儲在本地的指定目錄;同時當用戶需要使用指定的容器鏡像來創建容器的rootfs時,graphdriver從本地鏡像存儲目錄中獲取指定的容器鏡像。

在graphdriver的初始化過程之前,有4種文件系統或類文件系統在其內部註冊,它們分別是aufs、btrfs、vfs和devmapper。而Docker在初始化之時,通過獲取系統環境變量」DOCKER_DRIVER」來提取所使用driver的指定類型。而之後所有的graph操作,都使用該driver來執行。

graphdriver的架構如下:

networkdriver的用途是完成Docker容器網絡環境的配置,其中包括Docker啓動時爲Docker環境創建網橋;Docker容器創建時爲其創建專屬虛擬網卡設備;以及爲Docker容器分配IP、端口並與宿主機做端口映射,設置容器防火牆策略等。networkdriver的架構如下:

 

execdriver作爲Docker容器的執行驅動,負責創建容器運行命名空間,負責容器資源使用的統計與限制,負責容器內部進程的真正運行等。在execdriver的實現過程中,原先可以使用LXC驅動調用LXC的接口,來操縱容器的配置以及生命週期,而現在execdriver默認使用native驅動,不依賴於LXC。

具體體現在Daemon啓動過程中加載的ExecDriverflag參數,該參數在配置文件已經被設爲」native」。這可以認爲是Docker在1.2版本上一個很大的改變,或者說Docker實現跨平臺的一個先兆。execdriver架構如下:

9、libcontainer

libcontainer是Docker架構中一個使用Go語言設計實現的庫,設計初衷是希望該庫可以不依靠任何依賴,直接訪問內核中與容器相關的API。

正是由於libcontainer的存在,Docker可以直接調用libcontainer,而最終操縱容器的namespace、cgroups、apparmor、網絡設備以及防火牆規則等。這一系列操作的完成都不需要依賴LXC或者其他包。libcontainer架構如下:

另外,libcontainer提供了一整套標準的接口來滿足上層對容器管理的需求。或者說,libcontainer屏蔽了Docker上層對容器的直接管理。又由於libcontainer使用Go這種跨平臺的語言開發實現,且本身又可以被上層多種不同的編程語言訪問,因此很難說,未來的Docker就一定會緊緊地和Linux捆綁在一起。而於此同時,Microsoft在其著名雲計算平臺Azure中,也添加了對Docker的支持,可見Docker的開放程度與業界的火熱度。

暫不談Docker,由於libcontainer的功能以及其本身與系統的鬆耦合特性,很有可能會在其他以容器爲原型的平臺出現,同時也很有可能催生出雲計算領域全新的項目。

10、docker container

Docker container(Docker容器)是Docker架構中服務交付的最終體現形式。

Docker按照用戶的需求與指令,訂製相應的Docker容器:

  • 用戶通過指定容器鏡像,使得Docker容器可以自定義rootfs等文件系統;

  • 用戶通過指定計算資源的配額,使得Docker容器使用指定的計算資源;

  • 用戶通過配置網絡及其安全策略,使得Docker容器擁有獨立且安全的網絡環境;

  • 用戶通過指定運行的命令,使得Docker容器執行指定的工作。

  

參考文章:

https://cloud.tencent.com/developer/article/1006116 

http://39sd.cn/732DD

https://yq.aliyun.com/articles/65145

https://blog.51cto.com/10085711/2068290

https://www.cnblogs.com/zuxing/articles/8717415.html