深藏若虛

在 Docker Container 裡應該避免的 10 件事

10 things to avoid in docker containers

來源

本篇文章譯自 Rafael Benevides 在 2016/02/24 於 RED HAT DEVELOPER BLOG 上發表的 10 things to avoid in docker containers 一文。已寫信徵得原作者得同意以進行翻譯。

希望能透過本篇翻譯,讓臺灣社群對於 Docker container 的使用與理解有所幫助。 = )

譯文

嘿,看來您終於也投入 Container(譯註:本文若沒特別說明,Container 皆是指 Docker container)1 的懷抱了,相信您也發現它能夠解決很多問題並擁有很多優點:

  1. 不可變的(immutable):
    因為作業系統、函式庫(library)版本、設定、資料夾、應用程式都被包裝在 Container 裡頭,所以您能確保相同的 Image(譯註:本文若沒特別說明,Image 皆是指 Docker image) 2,在 QA 的測試下與正式環境中,都會擁有同樣的行為。

  2. 輕量的:
    Container 只使用少量的記憶體。不再需要耗費成千上百 MB 的記憶體,Container 只會使用主程序所需的用量,再多加上數十 MB 的記憶體而已。

  3. 快速的:
    您可以啟動 Container 就像是平時啟動 Linux 程序一樣快。不再需要耗費數分鐘,您可以在幾秒內就啟動一個全新的 Container 。

然而,很多使用者仍然對待 Container 像是以往對待虛擬機器一般,認為虛擬化技術該有的優點 Container 都沒落下,卻忘記了 Container 除此之外的另一個絕大優勢:它是一次性的(disposable)

Container 的使用哲學:「容器用於一時」3

Containers are ephemeral

這個特性「本身」促使使用者改變他們對於處理與管理 Container 的習慣。接下來我會解釋您不應在 Container 裡做什麼,以確保它能發揮最大效益。

一、不要在 Container 裡儲存資料(data)


Container 是可以被停止、摧毀、或是取代的。一個運行 1.0 版應用程式的 Container 應該要可以輕易被運行 1.1 版的 Container 輕易地取代,且不會影響或失去任何資料。如果您真的需要儲存資料,請將它存在 volume 4。不過如果兩個 Container 都對同一個 volume 寫進資料,要注意是否可能造成出錯,並確保您的應用程式是否有設計寫入共同資料的功能。

二、不要將應用程式分兩部份搬移

如同有些人會將 Container 視為虛擬機器,裡頭的多數人也會傾向認為應該要將應用程式部署在一個運行中的 Container。當您在開發階段這麼做倒無可厚非,因為您可能要持續地部署與除錯。但在持續交付5通往 QA 和正式環境的自動化 pipeline 流程裡,您的應用程式應該是 Image 的一部份。記住:Container 是不可變的

三、不要建立大型的 Image

一個大型的 Image 只會讓它難以被散佈。確認您是否只放置應用程式/程序所需的檔案和函式庫,不要在建置時安裝多餘的套件或是進行套件更新(像是 yum updateapt-get upgrade6,這樣會下載過多的檔案加進新的 Image 層。

四、不要使用單層式的 Image

為了有效率地使用分層式檔案系統(layered filesystem),請總是為 OS 建置您專屬的 Base Image,然後為使用者名稱定義執行時期所需安裝、設定、您的應用程式各獨立建置一層。這會讓您在 Image 的重建和管理更加簡易,並易於散佈。

五、不要用執行中的 Container 建立 Image

以行話來說,就是不要使用 docker commit 去建立 Image。這種方式建立的 Image 是難以重現的,應該要徹底避免。請務必使用 Dockerfile 或時其他可以完全重現的 S2I(source-to-image) 方式去做這件事。另外,若是您使用程式碼版本控制系統(如 git)去儲存 Dockerfile,您就可以追蹤 Dockerfile 的變動。

六、不要只使用 latest 標籤

latest 標籤就像是 Maven 使用者的 SNAPSHOT。多使用標籤,以善用分層式檔案系統的特性。您不會希望在您建置 Image 的幾個月後,驚訝的發現您的應用程式竟然不能執行,探究原因後才發現是因為父層級(Dockerfile 中的 FROM)被一個無法向下相容的新版本給取代了,或是因為從建置快取中取得錯誤的 latest 導致。latest 標籤也應該避免使用在正式環境下部署 Container,因為您不能追蹤您的 Container 到底是跑哪一個 Image 版本。

七、不要在一個 Container 跑超過一個程序

程序可以完美的去執行一個程序(像是 http daemon、application server、database),但如果您執行超過一個程序,您可能會在管理、讀取紀錄或獨立更新上都感到棘手。

八、不要在 Image 儲存憑証,請使用環境變數

不要將您的使用者名稱或是密碼寫死(hard-code)在 Image 中。請使用環境變數從 Container 外面取得這些資訊。像是 Postgres Image 就是一個很好的典範。

九、使用非 root 的使用者去執行程序

「Docker container 預設會使用 root 去執行程序。….隨著 docker 越來越成熟,會有更多安全的預設設定可以使用。現在,需要用 root 對其他人是有危險的,且可能無法在所有環境中使用。您的 Image 應該使用 USER 指令去指定非 root 的使用者讓 container 執行。….」——Guidance for Docker Image Authors

十、不要相依 IP 位址

每個 Container 都擁有他們自己內部的 IP 位址,並可能會在您啟動或停止 Container 時被改變。如果您的應用程式或是微服務需要跟另一個的 Container 溝通,請利用環境變數將合適的 hostname 和 port 從一個 Container 傳遞給另一個 Container 。

更多關於 Container 的資訊,請參考並註冊 http://developers.redhat.com/containers/

[][containers]

譯註

深刻體會到讀懂英文與翻譯成中文是兩回事。若有任何覺得翻譯不妥,或是覺得可以更好的建議,歡迎留言告知。最後特別感謝 Docker.Taipei 社群的先進 Philip ZhengWilliam Yeh 及友人 Davy猴子、Micheal、Chorld 提供諮詢與建議。


  1. Container,中文多翻為容器,本文特別指 Docker container,而非泛指所有 container。考證臺灣社群與相關報導,決定在文本維持英文,並採用原文使用小寫。,且為了與一般容器區隔,刻意使用首字大寫表示其為狹義性。 
  2. Image,中文在台灣社群多翻為映像檔,中國社群則為鏡像,本文特別指 Docker image,與虛擬機器的 image 概念不盡相同。考證臺灣社群與相關報導,決定在文本維持英文,並採用原文使用小寫。,且為了與虛擬機器的 image 區隔,刻意使用首字大寫表示其為狹義性。 
  3. ephemeral 在《牛津現代英漢雙語詞典》的解釋為「living, lasting, etc for a very short time 」,簡單來說就是「短命」的意象,這邊翻成用於一時,而不用常見的短暫臨時,是希望能保有活得不長的元素。當然,最直接的講法大概就是「容器命短」吧!但就對初學者來說不容易體會。 
  4. volume,在《Docker —— 從入門到實踐­》正體中文版翻作資料卷,在這裡採用原文會比較直觀。 
  5. continuous delivery,臺灣社群多翻為持續交付。通常會和持續整合、持續部署一起提到,簡單的定義可以參考山姆鍋對持續整合、持續部署、持續交付的定義,本文就不多描述了。 
  6. 因為台灣 Linux 社群在發行版的選擇上,以使用 Debian 及其衍伸發行版的使用者較佔多數,所以這邊比原文多加了 apt-get 的指令。需要注意的是 yum update 是等同 apt-get upgrade,而 yum makecache 才等同於 apt-get update。 

Collection ,Information Technology