標籤:

libcontainer實現原理

1、使用工廠Factory和容器配置container

libcontainer中的factory是創建一個邏輯概念上的「容器對象」,他並不是運行的容器,而只是包含又namespace和cgroups配置參數等的邏輯概念上的容器。

Factory創建容器的分為三步:

第一步,驗證容器參數的合法性,即:容器的啟動目錄(/var/lib/docker/container),容器ID,容器配置三者的合法性。

第二步,驗證將要上傳容器ID和現有運行容器ID之間沒有衝突。

第三步,在根目錄下創建(/var/lib/docker/container/{ContainerID})容器的工作目錄

第四步,返回一個Container對象,此對象包含容器ID、容器工作目錄、容器配置、初始化指令和參數,以及cgroup管理器等。

此時,如果執行完上述的步驟,表明容器已經創建完。

2、啟動邏輯容器container

在此過程中主要是創建兩個實例:

(1)process

上述第一步創建過程中,即:process過程

(2)parentprocess

第一步:創建一個管道,以後與外部進程通信

第二步:根據邏輯容器創建一個進程啟動的cmd對象,此對象是從容器中獲取命令執行的參數(命令路徑、命令參數、輸入和輸出、執行命令的根目錄和進程管道pipe等)

第三步:為cmd對象添加一些環境變數

第四步:配置容器啟動的namespace,表明容器是在哪個命名空間下啟動的。

第五步:將container中的容器配置和Process中的entrypoint信息合併為一份容器配置並加入到ParentProcess中。

3、用邏輯容器創建物理容器

第一步:Docker daemon利用exec包執行initProcess.cmd,起作用是初始化一個namespace

第二步:把容器進程dockerinit 的PID加入到cgroup中管理

第三步:創建容器內部的網路設備,包括lo和veth

第四步:通過管道發送容器配置信息給容器進程dockerinit

第五步:dockerinit 根據接收到的容器配置信息啟動容器

4、Docker daemon 與容器之間的通信

docker daemon與容器之間的通信方式採用的文件和文件描述符,具體實現是:

pipe(int fd[2])創建管道 fd[1]端寫入數據, fd[0]端讀物數據

調用pipe函數時,創建的子進程會內嵌這個打開的文件描述符,對fd[1]寫入數據後可以在fd[0]端讀取,這樣通過管道父子進程之間就可以通信了,最後當傳遞EOF信號時兩個進程之間的通信結束。


推薦閱讀:

如何通俗解釋Docker是什麼?
教程 | 使用 Docker 安裝深度學習環境
docker怎麼修改拉取源從指定的國內倉庫拉取鏡像?
如何評價docker?

TAG:Docker |