天天看點

什麼是 Docker ?

關于 Docker 是什麼,有個著名的隐喻:集裝箱。但是它卻起了個“碼頭勞工”(docker 的英文翻譯)的名字。

這無疑給使用者很多暗示:“快來用吧!用了 Docker,就像世界出現了集裝箱,這樣你的業務就可以随意的、無拘無束的運作在任何地方(Docker 公司的口号:Build,Ship,and Run Any App,Anywhere),于是碼頭勞工就基本都可以下崗了。”但是人們往往忽略了一個問題,隐喻的好處是友善人了解一個不容易了解的概念,但并不能解釋其概念本身。

網際網路技術行業的一大特點是,這裡的絕大多數事物并不像現實生活那麼具體,在這個行業中我們所接觸的絕大多數概念都是抽象的、不具體的。是以現實生活中很多可笑的事情在網際網路技術行業就不僅變的不可笑,反而可能很嚴肅。就比如,現實生活中你是幾乎不可能看見兩個神經正常的成年人争論到底是錘子更好還是螺絲刀更好這個問題的。而在我們這個行業,你可以很容易的被卷入到底是 java 好?還是 php 好?還是 js 好?或者類似的語言之争中。當然除了語言,其它的軟體工具之争也比比皆是,比如經典的還有 vim vs emacs。

由于不具體和抽象,就需要隐喻來給投資人解釋其價值,畢竟投資人大多數是外行嘛。至于 docker 到底是“集裝箱”還是“碼頭勞工”并不重要,即使這兩個概念本質上沖突了都不重要,很少有人會去真的思考集裝箱的出現導緻碼頭勞工幾乎絕迹。隻要能讓大家明白 docker 是個重要的、有價值的、劃時代的工具,騙到投資人的錢就足夠了。也很少有投資人去考究集裝箱的發明人到底有沒有是以賺到錢?以及為什麼沒賺到錢?隻要概念能忽悠人就行了。當然這個概念順便也忽悠了所有懶得思考的技術工程師。

吐了一大段槽之後,回到我們的正題,docker 到底是什麼?既然大家喜歡集裝箱這個隐喻,那麼我們也不妨先來看看集裝箱的本質。大家應該基本都了解集裝箱是怎麼改變世界的吧?在集裝箱之前,貨物運輸沒有統一的标準方式進行搬運,于是鐵路、公路、海洋等各種運輸之間,需要大量的人力作為貨物中轉,效率極低,而且成本很高。集裝箱出現之後,世界上絕大多數的貨物運輸都可以放到這個神奇的箱子裡,然後在公路、鐵路、海洋等所有運輸場景下,這個箱子都可以不用變化形态直接可以承運,而且中間的中轉工作,都可以通過大型機械搞定,效率大大提升。從此全球化開始,商業的潛力被進一步挖掘......牛逼之處我就不多說了,可是這個箱子為什麼這麼神奇呢?答案其實也就在上面的描述中,無非就是兩個字:标準。

是的!标準!标準!标準!重要的事情說三遍。

因為規範了集裝箱的大小和尺寸的規格标準,于是相應的船舶、卡車、列車才能按照規格制造出來使聯運成為可能,所有的運輸中轉的自動化工具才能被設計建造出來并且高效的使用,才可以極大的提高效率,提升自動化水準,以至于碼頭勞工才會失業。集裝箱本身是一個産品,而這個産品無非就是“标準化”的這個概念穿上了馬甲,馬甲可以有紅的、綠的、藍的、花的,但是大小規格必須都一樣。現實世界中的事實顯而易見,就是這麼簡單。那麼 docker 呢?

按照這個思路,docker 其實跟集裝箱一樣,或者說它想跟集裝箱一樣,成為穿着馬甲的“标準化”。這樣開發工程師就可以把它們開發出來的 bug 們放到“集裝箱”裡,然後運維人員就可以使用标準化的操作工具去運維這些可愛的 bug 們。于是實作了“海陸聯運”,就好像運維工程師根本不需要了解其運維的軟體架構而開發工程師也并不需要了解其軟體運作的作業系統一樣......

這就是 docker 的實質:穿着馬甲的标準化。docker 的發明人根據自己運維 PAAS 平台的經驗,重新思考了自己的工作,将 PAAS 平台的 devops 工作從各個角度标準化了一下,将系統底層實作的 cgroup、namespace、aufs|device mapper 等技術內建在一個使用鏡像方式釋出的工具中,于是形成了 docker。觀察 docker 形成的思考過程,其實就是作者針對他所運維的場景如何做自動化運維的思考,大家可以參見其演講的 ppt:Docker: automation for the rest of us。

這個演講的名字就跟自動化運維相關:Docker: automation for the rest of us 。那麼 Docker 的實質是什麼?在我看來就是個針對 PAAS 平台的自動化運維工具而已。衆所周知(當然如果你不知道,那麼我來告訴你):自動化運維的大前提就是标準化。

如果你正好是一個運維工程師而且你正感覺你的運維環境一團糟,麻煩請你思考一下這是為什麼?你是不是正在運維着一個使用 php、java、C#甚至 C/C++等用各種語言編寫的應用都在運作的環境裡?這個環境是不是因為某種曆史原因,使你的作業系統運作着各個版本的核心甚至還有 windows?即使是同樣語言編寫的業務也運作着不同版本的庫?你的整個系統環境是不是甚至找不出來兩台硬體、作業系統、庫版本以及語言版本完全一樣的環境?于是你每次遇到問題都要去排查到底那個坑到底在那裡?從網絡、核心到應用邏輯。你每次遇到産品更新都要在各種環境上做穩定性測試,發現不同的環境代碼 crash 的原因都不盡相同。你就像一個老中醫一樣去經曆各種疑難雜症,如果遇到問題能找到原因甚至都是幸運的,絕大多數情況是解決了但不知道原因和沒解決自動好了也不知道原因。于是你們在一個特定的公司的環境中積累着“經驗”,成為你們組新手眼中的大神,憑借曆經故障養成的條件反射在快速解決不斷發生的重複問題,并故弄玄虛的說:這就是工作經驗。因為經驗經常是搞不清楚原因時的最後一個遮羞布。當别人抱怨你們部門效率低的時候,你一般的反應是:”you can you up,no can no 逼逼!“

我花了這麼多口舌吐槽運維,無非就是想提醒大家”運維标準化的重要性“這一顯而不易見的事實。标準化了,才能提高效率。标準化了,才能基于标準建設屬于你們系統的自動化運維。那麼我們再來看看 docker 是怎麼做的?

首先,标準化就要有标準化的文檔規範,要定義系統軟體版本等一系列内容。規範好了之後,大家開始實施。但是在長期運維的過程中,很可能出現随着系統的發展,文檔内容已經過時了,工程師又來不及更新文檔的問題。怎麼解決?docker 給出的答案是:用 dockerfile。dockerfile 就是你的文檔,并且用來産生鏡像。要改變 docker 鏡像中的環境,先改 dockerfile,用它産生鏡像就行了,保證文檔和環境一緻。那麼現實是,有多少在使用 docker 的人是這樣用的?你們是不是嫌這樣麻煩,于是幹脆直接線上 docker commit 産生鏡像,讓文檔跟現場環境又不符了?或者我還是太理想,因為你們壓根連文檔都沒有?

其次,标準化要有對應用統一操作的方法。在現實中,即使你用的是 php 開發的應用,啟動的方式都可能不盡相同。有用 apache 的,有用 nginx 的,還有用某種不知名 web 容器的,甚至是自己開發 web 容器的。如果操作範圍擴大到包含 java 等其它語言,或資料庫等其它服務,那麼操作方式更是千奇百怪。雖然 UNIX 作業系統早就對此作了統一的規範,就是大家常見的把啟動腳本放到/etc/rc.d 中,SYSV 标準中甚至規定了啟動腳本該怎麼寫,應該有哪些方法。但是絕大多數人不知道,或者知道了也不這麼做,他們習慣用./start 作為自己業務啟動的唯一标準。甚至./是哪個目錄可能都記不住。于是 docker 又給出了解決方案:我壓根不管你怎麼啟動,你自己愛咋來咋來,我們用 docker start 或 run 作為統一标準。于是 docker start 可以啟動一個 apache、nginx、jvm、mysql 等等。有人病垢 docker 的設計,質疑它為什麼設計上一個容器内隻給啟動一個程序?這就是原因:人家壓根不是為了給你當虛拟機用的,人家是為了給啟動生産環境的程序做标準化的!

第三,為了維護生産環境的一緻性和配置變更的幂等,docker 創造性的使用了類似 git 管理代碼的方式對環境鏡像進行管理。于是:

你想做庫版本更新嗎?更新個鏡像吧! 你想做 php、java 的版本更新嗎?更新個鏡像吧。 好友善!太爽了! 等等......神馬?你想改變 apache 配置檔案中的一個字段?做個新鏡像更新吧! 你的 php 代碼寫錯了一行要改個 bug?做個新鏡像更新吧......

在一群人吐血三升之後,于是有人出了個主意。唉,其實後兩種需求沒必要這麼麻煩,有一種軟體叫做 puppet、chef、salt、ansible、rsync......

于是我們要在 docker 中啟動一個 puppet。

什麼?你要用 ansible?好吧,我們來看看怎麼在 docker 中啟動一個 sshd? 我有個計劃任務要跑,起個 crontab 可以麼?

你的 docker 是不是就這麼變成了“虛拟機”的?

不過請注意:我并不是說 docker 不好,隻是你是否真的評估了它标準話的方式是不是适合你的業務場景?錘子是用來砸釘子的,但是你非要用它來砸手指,我也沒什麼辦法。

作為一個工程師,而且是受過專業訓練的工程師,總是想設計出一套工具滿足所有場景需求。因為工程師所受的思維訓練是:你越是解決了更普遍的問題,你所創造的價值就越大。但是請搞清楚,這個任務一般是由标準委員會來完成的,每個工程行業都會有這麼個組織來做這件事情。當然,不排除商業公司的産品可以深刻影響标準制定的情況。

那麼我們這些工程師最大的價值是什麼?擺正自己的位置,看清自己的問題,幫組所在的企業進一步提高效率,提高競争力。每個企業都有其曆史和目前特點,就運維工作來講,根據企業的實際情況找到其标準化的最經濟有利方式才是我們這些受聘用的職業工程師的核心價值。軟體選型要要因地制宜,而不是跟風炒作。當然,如果你的核心價值是想要站在“技術前沿”,打算一直引領技術潮流,做一個出沒于各大技術交流會的新技術吹牛逼者,并以此擡高自己身價的話,那我的話自然是對你不适用的。(說這話可能會得罪很多人,我要解釋一下:對于那些真誠的想要分享自己技術,希望為社群發展做貢獻的人,我是懷着深深的敬意的!謝謝你們!)

對待新技術,大多數工程師的狀态是:測試是為了上線的,測試出的問題都是要解決的而不是用來評估的,不上線就沒有工作成果。我認為工程師對待新技術應有得态度是:激進的用新技術新方法來做線下測試,認真的總結評估測試流程和結果和現有環境的異同,保守謹慎的評估決策新技術是否在業務上大規模使用。

docker 是銀彈麼?真的能像集裝箱那樣改變世界麼?我的看法當然不是。即使集裝箱,也不能解決一些特殊的運輸問題,比如大型飛機零部件的運輸,或者小件零散商品的運輸。如果說雲計算行業真的要出現集裝箱的話,那麼首先這個行業要被幾大雲計算廠商瓜分完畢,市場成熟之後才有可能。為什麼?因為讓一個應用可以在任何地方跑的需求,主要應該來自雲的使用者,他們可能為了穩定性考慮既租用了阿某雲,又租用了騰訊雲(純廣告,自己所在的公司,是以請勿吐槽),還可能為了海外市場還用了某馬遜雲。這時使用者會有需求說,我想要這些雲的環境标準一緻,以便我的應用可以在哪朵雲上都能跑(Build,Ship,and Run Any App)。而現在,雲計算市場剛剛起步,群雄逐鹿,正是差異化發展争奪使用者的時候。出了雲計算廠商外,其它公司的 IT 環境都不一樣,标準化要求也就不可能一樣。那麼你覺得 docker 這個标準可能适合所有人麼?

如果你用過了 docker,并且還覺得它非常合适你的環境,那麼我希望你能回答這幾個問題:

你的 docker 是用 docker file 産生的鏡像還是直接 docker commit?

你的 docker 裡面跑了多少個程序?

你的 docker 是當虛拟機用的麼?

那麼你用的是 docker 麼?

最後,送大家一個段子,希望能博你一笑。

工程師:“嘿!有人發明了一個叫做集裝箱的東西,這東西一定可以使運輸成本大大下降!甚至改變世界!” 使用者:“好興奮!這東西可以運輸我的波音 787 客機麼?“ 工程師:“額。。不能整個運,需要拆開再運,因為我們要符合集裝箱的标準......” 使用者:“那這東西可以運輸我的空客 380 嘛?” 工程師:“額。。我們讨論的是同一件事情。” 使用者:“不行是嘛?那不能改造一下集裝箱讓它可以運嘛?” 工程師:“額。。。這不僅僅是我們的問題,要到達運輸目的地還要經過鐵路,公路,他們可能也無法......” 使用者:“真的不能改造集裝箱麼?可這東西是以後的發展方向啊!未來的世界都是應該是集裝箱運輸的!” 工程師:“額......” 老闆:“嗯!這東西說不定真的是未來的發展方向!我們一定要實作用集裝箱運輸這些飛機!工程師們,你們趕緊去攻克這些技術難題,早日可以實作我們使用者的特殊需求!讓集裝箱可以達到我們的業務要求!快去吧!加油啊!”