建構精簡版的 Deno 容器
很多年前「建構一個與 Ubuntu 相容的小型 Docker 映像」這篇文章中,山姆鍋提出為什麼偏好小型的容器映像檔,如今這個偏好依然存在。最近一時興起使用 Docker multi-stage 重新弄了一個 Basebox
容器,並以 Deno 作為示範。
新版 Basebox 特色
新版 Basebox 同樣基於 Ubuntu 系統,但只包含基本作業系統目錄結構、重要的動態連結程式庫,以及一個 nologin
執行檔; 去掉了 busybox
以及 bash
的支援。如果直接執行 sampot/basebox
會得到下列結果:
1 | $ docker run -it --rm sampot/basebox |
Basebox
設計作為其它容器的基礎,本身沒提供什麼直接用途。Basebox
適合用在容器只有封裝一個執行檔,但執行檔還需要系統存在一些必要的動態連結程式庫 (.so) 的情境。
使用 Basebox 作為 Deno 容器的基礎
Deno 是一個安全的 JavaScript 與 TypeScript 的執行環境,為 Node.js 之父 Ryan Dahl 所帶領開發。 雖然 Deno 的執行只需要一個執行檔,但還需要系統存在一些必要的動態連結程式庫 (.so),剛好適合拿來作為 Basebox
的範例。
找出 Deno 需要的動態連結檔
使用 ubuntu:18.04
容器,下載安裝 deno
後,使用 ldd
指令找出 deno
相依的動態程式庫有哪些。底下是一個執行範例:
1 | $ ldd /tmp/deno |
如果程式需要不存在 Basebox
容器中的動態連結程式庫 (共用物件檔),則需要從 ubuntu:18.04
容器額外複製到目標容器映像中。Basebox
剛好已經包含 Deno 所需的檔案,所以不需要額外複製動作。底下範例假設還需要 libgcc_s.so.1
檔,Dockerfile 中使用下列指令複製:
1 | COPY --from=builder /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib |
共用的動態程式庫都放置在 /lib 目錄中。
驗證 Deno 可以正常執行
底下是使用 sampot/deno
容器執行 welcome.ts
範例的結果:
1 | $ docker run -it --rm sampot/deno run https://deno.land/std/examples/welcome.ts |
sampot/deno
容器的相關程式碼可從 GitHub 取得,使用上的問題可以發 issue。
小結
這篇文章的出發點純粹只是因為技術上覺得有趣,除非對於容器映像檔大小以及容器安全性非常執著,不然應該不會有人自找麻煩吧!在 Kubernetes 還沒成為容器調度系統的事實標準前,在 Docker 容器內同時執行多個行程 (process) 有其合理用途,只要確保一個容器只負責一件事情,主行程之外都只提供輔助性的功能 (e.g. log 收集)。由於 Kubernetes Pod 允許多個容器共享網路以及本地檔案系統空間,在一個容器執行多個行程的需求應該會越來越少才對。
正面看待,容器內除了應用元件外,不包含任何其它執行檔可以進一步減少被攻擊面積,至於值不值得做到這個程度,就是見仁見智的問題了。