吐槽:Docker真的好嗎?

jopen 9年前發布 | 17K 次閱讀 Docker

本文是一篇對Docker“吐槽”的文章,作者從Dockerfile、緩存、分層文件系統、Docker Hub、安全、容器和虛擬機幾個方面入手,闡述了Docker和容器技術目前存在的一些問題,以至于說Docker的存在并沒有必要。大家可以把這篇文章 的觀點作為對Docker認識的一個補充,對Docker有一個更加客觀的認識。

概述

距離我上次發表對Docker的看法已經一年了,那個時候我狠狠的批評了Docker在架構上的缺陷以及其糟糕的用戶體驗。雖然現在項目已經發展到1.0,但是還是得到了一些來自亞馬遜的不滿,用戶失望程度也在不斷增加,面臨大量的指責,甚至還存在一些可能會導致主機污染的漏洞。然而Docker Hub上個人私有倉庫的引入,使得用戶自己不需要再運行個人的Registry,再加上webhook與GitHub整合,所有這些看起來是一個良好的開始。

于是我決定再給Docker一個“機會”,并且把其投入到生產中運行六個月,看看效果怎樣。結果真的令我很失望,在使用過程中,Docker表現 很令人失望,不但性能糟糕,而且由于其本身功能的不足,我們還需要在解決方案上不斷地進行變通,整個過程的用戶體驗也不盡如人意,這使得我幾乎想要把自己 的臉撞碎在桌子上!事實上,在我看來Docker的性能的確很糟糕,以至于緩存被禁用之后編譯過程變得更快。(看看reddithackernews上面討論)

Dockerfile

Dockerfile有很多問題,在我看來,他很丑陋,有很多局限性,有的地方甚至相互矛盾,并且有很多根本性的缺陷。讓我們來說說,假如你想創 建單個倉庫的多個鏡像,例如第二個鏡像包含了調試工具, 但是對兩個鏡像的基本要是是一樣的。Docker不支持這樣操作(per #9198), 當前并沒有能力去對Dockerfile進行擴展(per #735),使用子目錄的話會破壞創建的上下文以及阻止你使用ADD/COPY(per #2224), 就像管道一樣(per #2112),在容器構建的時候(build time)你也不能夠使用環境變量根據不同的運行條件來改變指令(per #2637)。

我們的變通方案是創建一個基礎的鏡像,兩個指定環境的鏡像,以及一些包含重命名和sed替換的Makefile自動化腳本。還有一些意想不到不到的“特性”導致$HOME環境變量消失了,還會產生一些沒用的錯誤信息,使用起來的確很不方便。

Docker 緩存/分層

Docker可以使用COW(copy-on-write)文件系統來緩存Dockerfile指令, 類似于LVM的快照,到現在仍然僅僅支持滿是問題的AuFS(AnotherUnionFS)。為了提高穩定性以及性能,之后在0.7版本中對COW做了不同的實現, 你可以在這里了解到詳細的情況。但是這個緩存系統并不智能,導致了一些令人驚訝的情況,比如不能阻止某一個指令被緩存(per #1996)。并且很慢, 鑒于這一點,如果你禁用緩存或者是避免使用分層,創建的速度反而快一點, 在Docker Hub上傳和下載的時候這個表現的更嚴重,詳情會在下面部分進行描述:

這些問題都是由Docker的架構設計導致的,Docker作為一個整體,總是線性的執行指令,即便是在很不合適的情況下也這樣 (per #2439)。作為一個改變慢速創建的變通方法,你可以使用一個第三方支持異步執行的工具,例如Salt SlackPuppet,甚至Bash,這樣的話就完全放棄分層的思想使其毫無用武之地。

Docker Hub

Docker鼓勵通過Docker Hub來進行社交合作, 允許你發布自己的Dokerfiles,不管是公有的還是私有的,這樣其他人可以基于此來通過FROM來進行擴展,而不是拷貝,粘貼。這個生態系統類似于AWS marketplace的AMIs,以及Vagrant的boxes,原則上說是非常有用的。

然而由于一些原因,Docker Hub在實現上是有缺陷的。Dockerfile不支持多FROM指令(per #3378, #5714 and #5726), 這就意味著你只能繼承自單個的鏡像。并且他也沒有強制版本化, 例如dockerfile/ubuntu:14.04的作者可以替換掉這個標簽的內容,這就相當于在使用了沒有強制版本的包管理工具。另外在后面也會提 到,Docker Hub在速度上的缺陷也很令人失望。

Docker Hub也有一個自動構建的系統,它可以監測倉庫中新的提交,并且觸發一個容器的創建。因為很多原因,這個功能基本上是沒用處的。創建服務沒有可定制化的功 能,甚至連最基本的前/后腳本鉤子也沒有。它還強制使用一個指定的項目結構,希望在根目錄中只有單一的Dockerfile,導致創建過程變得相當的慢, 也破壞了我們之前提到的創建的變通方法。

我們采用的變通方法是使用CircleCI, 一個持續集成(CI)平臺,可以觸發基于Makefile的Docker創建, 并推送到Docker Hub。這個并不能解決速度慢的問題, 唯一的解法就是使用我們自己的Docker Registry,這樣做確實有點復雜甚至可笑。

安全

Docker原來使用LXC作為默認的執行環境,從0.9之后采用libcontainer作為默認的執行環境。當使用合適的執行驅動(exec-driver)時,引入它來調整命名空間的能力,權限以及使用定制的LXC配置

Docker需要一個根守護進程一直在主機上運行,并且有很多安全漏洞,比如CVE-2014-6407CVE-2014-6408,非常坦率的說,這還不應該排在第一位。即便是Gartner, 根據他們可憐的評估記錄,也表達了對Docker不成熟,以及安全問題的擔憂。

Docker,從設計上來說,對namespace能力過 分的信任,但實際上namespace比一般的hypervisor暴露的攻擊面要大很多,Xen在Linux里面有129個CVEs(Common Vulnerabilities and Exposures),與之相比它卻有1279個。當然,這在某些情況下也是可以接受的,比如在Travis CI里面以公有的方式來構建, 但是在私有情況下和多用戶的環境下,就顯得比較危險了。

容器不是虛擬機

namespaces和cgroups是非常強大的,允許一個進程及其子進程有一個共享內核資源的私有視圖, 例如網絡棧和進程表。這種粒度的控制和隔離,加上chroot jailing和grsec, 可以提供一個很優秀的保護層。 有些應用, 例如uWSGI, 直接對這些優點加以利用,而不是通過Docker。 還有些應用不直接支持namespaces的可以用firejail封裝成沙箱。如果你覺得很冒險的話, 你也可以直接在你的代碼里面支持namespace。

容器化項目,諸如LXC和Docker, 利用這些特性,可以高效的在一個相同的內核空間中運行多個linux的發行版。與hypervisor相比,它們有時候會有一些優點,比如占用更少的內存并且啟動速度更快。 但是這是以損失完全性,穩定性和兼容性為代價的。這里有一個跟Linux內核接口有關的邊緣情況, 在內核和用戶空間運行非兼容的和沒有經過測試的glibc版本組合會導致一些不可預料的行為。

回到2008年, 當LXC被設想出來的時候,硬件輔助的虛擬化才有幾年的時間, 很多hypervisor有性能和穩定性的問題,這樣的虛擬化并沒有被廣泛的使用,也只是為了降低花費和減少物理機而做了折衷。但是現在 hypervisor的性能已經可以和物理機器一樣快了,有趣的是,在一些情況下可能更快。運行自定義的虛擬機也變的更快更便宜,隨著DigitalOcean在性能和花費方面不斷的超越EC2, 使得以一對一的方式運行應用和虛擬機,在財政上變的成為可能。

Bryan Cantrill在這里指出, 虛擬化的性能主要取決于工作負載的類型,比如IO很重的應用會導致更低的性能。

對于有些特定的情況,使用容器化是正確的選擇, 但是除非你能很明確的解釋為什么你要使用容器,否則你便可以使用hypervisor來代替。即便是你使用了傳統的虛擬化,你也可以直接應用namespaces的優勢,諸如firejail就可以幫助你的應該在缺少本地支持的情況下來實現這樣的特性。

Docker是沒有必要的

Docker增加了一個復雜的入侵層,這使得開發,故障排查以及調試變得非常困難, 常常制造的問題比解決的問題還多。這對部署沒有一點好處,因為你仍然需要使用的快照來達到自動擴展的目的。更糟糕的是,如果你不使用快照的話,你的生產環 境的擴展需要取決于Docker Hub的穩定性。

這個已經被baseimage-docker這個項目濫用了,這個鏡像試圖通過運行init.d作為入口使得檢查、調試,以及兼容變得更容易,它還嘗試提供給你一個可以用ssh登錄的服務器,從而把一個容器看成是一個虛擬機,盡管作者使用了很無力的論據去反駁這一點。

結論

如果你的開發工作流非常的健全,那么就應該已經明白Docker是沒有必要的。所有它宣傳的特性要么是沒用的要么就是實現的非常差,并且它主要的特性直接可以使用namespaces來完成。Dokcer本來應該是8年前的一個很可愛的想法,但是今天已經沒什么用了。

更正/修訂

表面上看,Docker有很多值得關注的地方。它鼓勵開發人員圍繞一個一成不變的部署流程, 可以快速的,簡單的開始一個新的項目,還有些其他的人認為有用的東西。但是需要提醒大家的是,本文是聚焦在一個每日的,長期使用的Docker上面,包括本地和生產環境。

盡管大多數提到的問題都是顯而易見的,本文并沒有為Docker如何變得更好提出什么建議。對Docker來說有很多解決方法,畢竟不管什么項目都是有優缺點的,我會在接下來的文章中作詳細的解釋。

a-ko對使用容器化有個長期的討論,markbnj也有一個詳細的技術反駁,這兩個都是很有用的。

我想對所有給他們反饋的人說聲謝謝,看到大家很喜歡我的寫作風格感覺非常的高興,我也讀了幾個高級工程師的回應, 包括那些欣賞我的人,這非常震撼人心。

原文鏈接:Lets review.. Docker (again)(翻譯:左偉 校對:王哲)

===========================
譯者介紹
左偉,現就職于IBM,軟件工程師,現從事于DevOps相關的研究,實現和推廣。

來自:http://dockerone.com/article/194

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!