關於 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 的實質是什麼?在我看來就是個針對 PaaS 平台的自動化運維工具而已。眾所周知(當然如果你不知道,那麼我來告訴你):
自動化運維的大前提就是標准化。
如果你正好是一個運維工程師,而且你正感覺你的運維環境一團糟,麻煩請你思考一下這是為什麼?你是不是正在運維著一個使用 php、java、C# 甚至 C/C++ 等用各種語言編寫的應用都在運行的環境裡?這個環境是不是因為某種歷史原因,使你的操作系統運行著各個版本的內核,甚至還有 windows?即使是同樣語言編寫的業務也運行著不同版本的庫?你的整個系統環境是不是甚至找不出來兩台硬件、操作系統、庫版本以及語言版本完全一樣的環境?於是你每次遇到問題都要去排查到底那個坑到底在那裡?從網絡、內核到應用邏輯。你每次遇到產品升級都要在各種環境上做穩定性測試,發現不同的環境代碼 crash 的原因都不盡相同。你就像一個老中醫一樣去經歷各種疑難雜症,如果遇到問題能找到原因甚至都是幸運的,絕大多數情況是解決了但不知道原因,和沒解決自動好了也不知道原因。於是你們在一個特定的公司的環境中積累著“經驗”,成為你們組新手眼中的大神,憑借歷經故障養成的條件反射在快速解決不斷發生的重復問題,並故弄玄虛的說:這就是工作經驗。
因為經驗經常是搞不清楚原因時的最後一個遮羞布。當別人抱怨你們部門效率低的時候,你一般的反應是:”you can you up,no can no BB!“
我花了這麼多口舌吐槽運維,無非就是想提醒大家”
運維標准化的重要性“這一顯而不易見的事實。標准化了,才能提高效率。標准化了,才能基於標准建設屬於你們系統的自動化運維。那麼我們再來看看 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 是用 dockerfile 產生的鏡像還是直接 docker commit?
你的 docker 裡面跑了多少個進程?
你的 docker 是當虛擬機用的麼?
那麼你用的是 docker 麼?
最後,送大家一個段子,希望能博你一笑。
工程師:“嘿!有人發明了一個叫做集裝箱的東西,這東西一定可以使運輸成本大大下降!甚至改變世界!”
用戶:“好興奮!這東西可以運輸我的波音787客機麼?“
工程師:“額。。不能整個運,需要拆開再運,因為我們要符合集裝箱的標准……”
用戶:“那這東西可以運輸我的空客380嘛?”
工程師:“額。。我們討論的是同一件事情。”
用戶:“不行是嘛?那不能改造一下集裝箱讓它可以運嘛?”
工程師:“額。。。這不僅僅是我們的問題,要到達運輸目的地還要經過鐵路,公路,他們可能也無法……”
用戶:“真的不能改造集裝箱麼?可這東西是以後的發展方向啊!未來的世界都是應該是集裝箱運輸的!”
工程師:“額……”
老板:“嗯!這東西說不定真的是未來的發展方向!我們一定要實現用集裝箱運輸這些飛機!工程師們,你們趕緊去攻克這些技術難題,早日可以實現我們用戶的特殊需求!讓集裝箱可以達到我們的業務要求!快去吧!加油啊!”
工程師:“額……”