Diffoci:讓容器建構可重現的驗證捷徑
Diffoci 來自 reproducible-containers/diffoci,它把容器的每一層、清單和設定拆解成容易比較的片段,用以檢查本地建構或 CI 執行是否真的可重複輸出同樣的映像。這篇分享 Diffoci 的角色、驗證流程與 CI 整合思路,讓你不必再用人工 diff 無數個 tarball。
何謂 Diffoci
Diffoci 的核心概念是「解構」容器映像。它會把 OCI image layout 和映像內部的檔案系統逐一展開成 tarball,再比對 metadata(manifest、config)與物理內容,這樣就能照顧到檔案權限、時間戳與層順序等細節,而不是只比較映像 ID。
比較時,Diffoci 會提供可經驗證的差異報表(包括檔案新增/刪除、二進位內容差異、metadata 不一致),也能把結果存成檔案以供追查。若你在本地手動 build 出來的映像與上游 CI 給的 artifact 有差異,Diffoci 能指出是哪一層、哪個檔案不對,甚至反推是否是建構參數或 buildkit cache 導致。
驗證流程切片
Diffoci 支援把驗證拆成幾個步驟,方便串到工作流程:
- 拉出參考映像:先把前次可信任的映像或某個 release 下載成 OCI layout(例如
docker save+umoci unpack),作為 baseline。 - 產生待驗證映像:用相同 Dockerfile/BuildKit pipeline 產出新的映像,並將它也轉成 OCI layout。
- 執行 Diffoci 比對:用
diffoci diff(或類似指令)比較兩個 OCI layout,差異會分門別類地列出檔案層、metadata 層與 config 層的差異。 - 分析報告:Diffoci 可輸出 XML/JSON 或 human-readable 形式的報告,並載入到 CI artifact,以便快速定位檔案不一致、層內重複或時間戳漂移等問題。
- 回饋開發流程:若差異在不可接受範圍(例如確保 byte-for-byte 相同),可以直接使該步驟 fail;若只是時間戳變動,可透過指令清除 metadata,確認誤判再走下一輪。
這種分層比較讓你不必猜測哪個檔案被改寫,也避免單純比較 digest 時疏漏時間戳或權限的變化。此外,這個流程也可套用在多平台建構(例如 amd64 與 arm64),只要把不同平台的映像各自解構,就能逐層對齊差異。
把 Diffoci 拉進 CI
在 CI(比如 GitHub Actions、GitLab CI)中,只要把 Diffoci 當成一個步驟來執行,就能在建構完成後立刻驗證結果:
- 先執行 build,產生映像與 OCI layout。
- 從 release 或 artifacts 下載先前的 OCI layout 作 baseline。
- 以 Diffoci 比對兩者,Diffoci 會回傳差異數據與檔案清單。
- 根據 policy 決定:若要 strict reproducibility,就讓差異導致 job fail;若只需資料一致,就把報告存起來讓人 review。
透過 Diffoci 的報告還可以自動化產生監控告警,例如「新映像多出了私密金鑰」或「某系統套件版本被升級」,以便在 release 前即時攔截潛在風險。
小結
Diffoci 並非單純把映像 tarball 做 diff,而是把 OCI 元素拆解成會被 CI 消費的維度(metadata、層、檔案內容),再提供可讀報告與 exit code,讓可重現性從「理想」變成「pipeline guard」。若你的團隊在意每次 build 的 bitwise 相同性,或希望在多個環境比對結果,Diffoci 是一個值得納入的檢查步驟。