Skip to main content

3 posts tagged with "Docker"

View All Tags

· 3 min read

標題: 「Dockerfile 中透過 COPY --chomd 比透過 RUN chomd 可以省下更多空間」 類別: containers 連結: https://blog.vamc19.dev/posts/dockerfile-copy-chmod/

本篇文章是作者探討自己建制 Image 中所發現的一些有趣事實。 作者使用一個大概 70MB 的 image,並且安裝與運行大概 90MB 左右的額外空間,結果最後整個 image 高達 267 70MB 因此作者就花了一些時間來研究整體原因並且嘗試理解到底發生什麼事情

作者首先檢視自己的 Dockerfile,其內容簡單不複雜,包含如 COPY 一個 Binary (該 Binary 80 MB 左右) RUN xxxxx 等常見用法。

詳細檢視所有的 layer 資訊後,作者發現 RUN 這個指令竟然產生了 94.4MB 的全新 layer,而就是這個 layer 導致整體空間變成 267 MB. 作者的 RUN 指令執行

  1. 透過 apt-get 安裝四個套件
  2. 透過 chmod 將前述 COPY 來的檔案給予執行的權限
  3. 創建資料夾

作者檢查過安裝的套件,大概只有 6MB 左右,但是整個 layer 很明確就是多了 94.4 MB 出來,因此經過測試與研究後,作者觀察到 當移除第二步(修給檔案給予執行的權限)後整個空間瞬間變得很小,整體 image 最後的大小就符合預期的 174MB。

所以整個問題就出來了,為什麼單純執行一個 RUN chmod 就會使得整個 image layer 變大? 簡單來說 image 的底層是基於 OverlayFS,而 OverlayFS 的一大特色就是 CoW, Copy on Write,作者起初覺得 我只是透過 chmod 去修改該 Binary 一個屬性而以,本身並沒有寫入檔案到檔案系統中,怎麼會產生這麼大的檔案變化?

仔細研究 OverlayFS 的文件後終於水落石出,原來除了寫入檔案外,修改檔案的某些 metadata 也會觸發 CoW 的機制

When a file in the lower filesystem is accessed in a way the requires write-access, such as opening for write access, changing some metadata etc., the file is first copied from the lower filesystem to the upper filesystem (copy_up).

至於為什麼修改個 metadata 也要觸發 CoW 主要是跟安全性有關,文章中有關於這部分的額外連結,有興趣的可以參考

· One min read

連結: https://emmer.dev/blog/docker-shell-vs.-exec-form/

Docker 基本介紹文,不知道常寫 Dockerfile 的讀者能不能分清楚 Dockerfile 內 Shell 與 Exec 兩種格式的差異 RUN, CMD, ENTRYPOINT 等指令都同時支援這兩種格式 Shell 格式就是 RUN command arg1 arg2 arg3 這種直接描述的格式,而 Exec 則是用 [] 包起來,每個參數單獨敘述,譬如 RUN ["command", "arg1", "arg2", "arg3"] 等。 本篇文章推薦 RUN 指令採取 Shell 格式而 CMD/ENTRYPOINT 都應該採用 EXEC 格式。 如果自己不清楚差異以及沒有想法為什麼平常自己這麽寫的話可以參考全文

· 3 min read

ref: https://jpetazzo.github.io/2021/11/30/docker-build-container-images-antipatterns/

本篇文章分享的是建置 Container 中的 Anti-Patterns,不講哪些好反而探討哪些不好。

文內列舉了不同的主題,包含

  1. Big images
    • All-in-one mega images
    • Data sets
  2. Small images
  3. Rebuilding common bases
  4. Building from the root of a giant monorepo
  5. Not using BuildKit
  6. Requiring rebuilds for every single change
  7. Using custom scripts instead of existing tools
  8. Forcing things to run in containers
  9. Using overly complex tools
  10. Conflicting names for scripts and images

以下針對內文幾個部分摘錄一下為什麼作者認為是個不好的模式

Small Images

Image 小本身不是什麼問題,但是有時候過度追求容量會使得一些常用有幫助的工具沒有辦法於容器內執行,這可能會導致未來要除錯時要花費更多的時間去處理,可能要研究如何重新安裝該工具等。

作者有強調這個議題是非常看環境與需求的,有些情況可能團隊根本不需要進入到容器內去執行 shell 來處理,有些可能會需要到容器內執行 ps, netstat, ss 等指令來觀察不同狀態。 作者推薦可以使用 gcr.io/distroless/static-debian11 這個 image 做為基礎然後將其之間的 busybox 給複製環境中,至少確保有基本工具可以使用

Not using BuildKit

BuildKit 是 docker build 的新版建置方式,相對於舊版方式來說 Buildkit 提供了更多功能,譬如平行建置,跨平台建置甚至效能上也會比過往的更好。 為了讓舊有使用者可以無痛轉移,所以 BuildKit 完全相容既有的 Dockerfile 的語法,所以切換方面是完全無腦的。 目前新版的 Docker Desktop 基本上已經預設採用 BuildKit 來進行建置,不過某些系統譬如 Linux 的環境下,還是需要透過設定環境變數來啟用這個功能,譬如 DOCKER_BUILDKIT=1 docker build . 等方式來建置。

此外透過 BuildKit 建置的產生結果跟過往不同,所以只要看建置結果的輸出就可以判別自己是否使用 BuildKit。

剩下的8個項目就留給有興趣的讀者自行閱讀