docker 源碼入門

前言

docker是go語言編寫的星澳,要看docker源碼,最起碼要學會go的基礎語法髓迎。

了解 docker 基礎架構 以后峦朗。可以對源碼總體結構有一個大體了解排龄,然后就可以順利的進行源碼的入門解讀了甚垦。

本文主要剖析 docker-ce 的源碼。

docker-ce github:
https://github.com/docker/docker-ce

環(huán)境

操作系統(tǒng):centos7
docker版本:docker-ce: 18.09

正文

docker 源碼簡介

https://github.com/docker涣雕,這里是docker源碼的家目錄艰亮。
可以看到這里有許多許多的項目,比如:docker-engine挣郭、docker-ce迄埃、cli等,這些項目和docker的架構都有關系兑障,我安裝時就只安裝了一個侄非,為啥這里這么多?到底如何查看流译?

首先要說一點逞怨,docker這個項目的源碼挺雜。

docker 家目錄下包含:docker-engine福澡、docker-ce叠赦、cli等。

進入docker-ce可以發(fā)現(xiàn) components下也有cli 和 engine革砸。

通過簡單得對比除秀,發(fā)現(xiàn)docker-ce下得cli 和 engine與docker家目錄下得docker-engine和cli是一樣得。也就是docker-ce只是組合了docker-engine算利,cli等册踩。

還有一個概念需要提,docker項目 fork 自 moby效拭。

進入到 docker-ce 中,
可以在 components 中看到:

components

在我們安裝完docker時暂吉,使用 docker version 命令可以看到一個docker client和一個docker server胖秒。docker client 對應這里的cli;docker server對應這里的engine慕的。
至于那個package扒怖,可以暫時不用管它。

當我們使用 docker start <container> 业稼。一個容器是如何被啟動起來的盗痒?

閱讀源碼前,可以先猜測一下主體流程:

  1. 如何生成命令行供我們使用低散?
  2. 在調用命令行后俯邓,如何訪問到docker server 提供的 restful api?
  3. docker engine 一定在監(jiān)聽 restful api 對應的地址!
  4. docker engine 收到指令熔号,接下來如何執(zhí)行稽鞭?
  5. docker engine 執(zhí)行完,我們也可以收拾收拾進入下一階段的學習了引镊!
docker 源碼解讀

根據(jù)上文猜測的 啟動容器 流程朦蕴,進行源碼解讀。
兩個部分:

  1. 命令行:https://github.com/docker/docker-ce/tree/18.09/components/cli
  2. server :https://github.com/docker/docker-ce/tree/18.09/components/engine
1. 如何生成命令行供我們使用弟头?

很明顯了吩抓,這是cli組件。那么直接進cli目錄中進行翻看赴恨。(注:docker 使用 cobra 這個包去實現(xiàn)命令行功能疹娶。)

每一個功能模塊或程序都會存在一個入口函數(shù)。

根據(jù)經(jīng)驗伦连,docker.go是功能的入口雨饺,它在:https://github.com/docker/docker-ce/blob/18.09/components/cli/cmd/docker/docker.go

入口函數(shù)找到了,先放到一邊』蟠荆現(xiàn)在去找具體命令行實現(xiàn)的地方额港。

現(xiàn)在去到 https://github.com/docker/docker-ce/tree/18.09/components/cli/cli/command 這個目錄下。這個目錄下的子目錄歧焦,看著是不是稍微有點眼熟移斩?使用 docker --help 列出來的子命令,有一個算一個倚舀,分別對應這些子目錄叹哭!

排查容器啟動流程忍宋,當然去container目錄下痕貌,進入container目錄后,可以清晰的看到容器相關命令對應的文件糠排!到這里舵稠,可以看出docker cli的目錄結構和命令行的結構十分相似!

找到 start.go,主要代碼如下:

image.png

稍微去了解了一下 cobra 哺徊。根據(jù)其使用方式室琢,可以知道這里就是定義docker start 命令的地方了。上圖標注處落追,是下面第2步驟需要分析的代碼盈滴。

至此,命令定義的地方已經(jīng)找到轿钠,接下來就是分析命令如何執(zhí)行巢钓。

2. 在調用命令行后,如何訪問到docker server 提供的 restful api?

在上面那張圖里的 runSatrt 方法中可以發(fā)現(xiàn) 啟動容器指向 dockerCli.Client().ContainerStart疗垛。如下:
https://github.com/docker/docker-ce/blob/18.09/components/cli/cli/command/container/start.go

image.png

結合導包症汹,dockerCli 指向 command.Cli , 而 command.Cli 中的 Client 指向 docker/docker/client。如下:
https://github.com/docker/docker-ce/blob/18.09/components/engine/client/client.go

image.png

現(xiàn)在 client 已找到贷腕,接下來順著 client 去找 ContainerStart 背镇。
在當前client下并沒有發(fā)現(xiàn)目標方法。這也是go的一個特點泽裳,其它的文件也可以聲明成該client瞒斩。
最后在 container_start.go 發(fā)現(xiàn)了目標方法,如下:
https://github.com/docker/docker-ce/blob/18.09/components/engine/client/container_start.go

image.png

如上圖涮总,這個 ContainerStart 方法調用的是 cli.post济瓢。很明顯的,這是一個訪問restful api的封裝方法妹卿。

至此旺矾,客戶端行為基本結束。向 "/containers/<containerID>/start" 地址發(fā)送了一個post請求夺克。

接下來便是去服務端找到監(jiān)聽這個地址的方法箕宙。

3. docker engine 一定在監(jiān)聽 restful api 對應的地址!

對于一個web server铺纽。路由可以幫助我們快速找到地址對應的方法柬帕。

現(xiàn)在,進入到engine目錄下狡门,開始分析源碼陷寝。

類似于 cli 組件,engine 組件也有入口函數(shù)其馏。也叫 docker.go凤跑。這個文件了解就好,暫時不會用到叛复。

路由的定義如下:
https://github.com/docker/docker-ce/blob/18.09/components/engine/api/server/router/container/container.go

image.png

至此仔引,路由已然找到扔仓。接下來就是分析 postContainersStart 這個方法干了什么。

4. docker engine 收到指令咖耘,接下來如何執(zhí)行翘簇?

postContainersStart 方法位于:
https://github.com/docker/docker-ce/blob/18.09/components/engine/api/server/router/container/container_routes.go

image.png

在當前方法中,可以看到引用了 backend.ContainerStart 儿倒。

https://github.com/docker/docker-ce/blob/18.09/components/engine/api/server/router/container/backend.go 中可以找到 ContainerStart 的定義版保。具體由daemon實現(xiàn)。

daemon位于:https://github.com/docker/docker-ce/blob/18.09/components/engine/daemon夫否。

其中 start.go 就是我們需要找的目標文件找筝,如下:
https://github.com/docker/docker-ce/blob/18.09/components/engine/daemon/start.go

image.png

當前方法指向:daemon.containerStart ,該方法就在當前文件中慷吊。

到這里應該已經(jīng)差不多了袖裕,我們不是要從零開始寫一個docker。

擴展

總結:

  1. 命令行或者sdk均是訪問 docker server 的restful api溉瓶。
  2. docker server 源碼總體層次:【api】--【daemon】急鳄。api 定義路由,daemon實現(xiàn)路由中的具體方法堰酿。
  3. docker-ce 中的cli和engine略有交叉疾宏,對于常見 c/s 架構,這種代碼交叉的情況比較少触创。一般 client 為單獨部署的方式坎藐,而docker 并沒有將cli獨立出來,可能是由于設計初衷就不是集群模式哼绑。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末岩馍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子抖韩,更是在濱河造成了極大的恐慌蛀恩,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茂浮,死亡現(xiàn)場離奇詭異双谆,居然都是意外死亡,警方通過查閱死者的電腦和手機席揽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門顽馋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人幌羞,你說我怎么就攤上這事寸谜。” “怎么了新翎?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵程帕,是天一觀的道長住练。 經(jīng)常有香客問我地啰,道長愁拭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任亏吝,我火速辦了婚禮岭埠,結果婚禮上,老公的妹妹穿的比我還像新娘蔚鸥。我一直安慰自己惜论,他們只是感情好,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布止喷。 她就那樣靜靜地躺著馆类,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弹谁。 梳的紋絲不亂的頭發(fā)上乾巧,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音预愤,去河邊找鬼沟于。 笑死,一個胖子當著我的面吹牛植康,可吹牛的內容都是我干的旷太。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼销睁,長吁一口氣:“原來是場噩夢啊……” “哼供璧!你這毒婦竟也來了?” 一聲冷哼從身側響起冻记,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嗜傅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后檩赢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吕嘀,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年贞瞒,在試婚紗的時候發(fā)現(xiàn)自己被綠了偶房。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡军浆,死狀恐怖棕洋,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情乒融,我是刑警寧澤掰盘,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布摄悯,位于F島的核電站,受9級特大地震影響愧捕,放射性物質發(fā)生泄漏奢驯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一次绘、第九天 我趴在偏房一處隱蔽的房頂上張望瘪阁。 院中可真熱鬧,春花似錦邮偎、人聲如沸管跺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽豁跑。三九已至,卻和暖如春泻云,著一層夾襖步出監(jiān)牢的瞬間艇拍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工壶愤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留淑倾,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓征椒,卻偏偏與公主長得像娇哆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子勃救,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內容