可重現建置
可重現建置是指任何人以相同的建置環境與建置指令,建置相同的原始碼時,都能得到逐位元完全相同的輸出。
最後更新:2026年11月11日
可重現建置(reproducible build)是指任何人以相同的建置環境與相同的建置指令,建置相同的原始碼時,都能得到逐位元完全相同的輸出。這是 Reproducible Builds 專案的定義。這裡的輸出是指建置所要產出的建置產物:執行檔、發行套件、容器映像檔或檔案系統映像檔。日誌不算在內。「能再建置一次」並不是同一件事;可重現代表位元組完全一致。
為什麼多數建置無法重現
- 在建置時解析相依套件。 沒有鎖定檔(lockfile)時,套件管理工具會在建置執行時選擇版本。PyPI 的解析結果可能因回應抵達的順序而不同,版本範圍會在新版本發布時移動,而
latest這類可變標籤也會指向新的位置。 - 環境。 時間戳記、檔案路徑、語系設定與主機本身的工具,都會進入建置產物中。
- 隨機性。 建置步驟可能會產生 ID、依雜湊值排序檔案,或每次以不同順序平行處理工作。
因此,連續兩次建置同一個 commit,並不保證會得到相同的結果,也不保證會得到相同的 SBOM。若建置下載了鎖定檔未列出的程式碼,也就是隱藏相依套件,情況會更糟。
團隊如何讓建置可重現
- 固定並鎖定每一項輸入,包括以 digest 固定基礎映像檔、以版本固定工具(請參閱鎖定檔)。
- 使用固定時間而非系統時鐘:
SOURCE_DATE_EPOCH是一個標準環境變數,存放 Unix 時間戳記,供建置工具取代目前時間使用。 - 移除或正規化建置路徑、排序檔案清單,並固定語系設定。
- 在工具鏈本身也已固定的封閉(hermetic)環境中建置。Nix 是做到這一點的方法之一。
- 實際驗證:在彼此獨立的條件下(另一台機器、另一個路徑、另一天)建置同一個 commit 兩次,並比較輸出。雜湊值不同時,diffoscope 會精確顯示哪裡有差異。
Yocto Project 說明了為什麼可重現性是需要驗證、而非可以假設的特性。其文件指出,該專案的建置自 3.1 版起「直到二進位層級(包括時間戳記)」皆可重現,只有 BitBake 與 OpenEmbedded-Core 保證完全可重現,而且「一旦加入其他 layer,這項保證就會失效」。該專案以 oe-selftest 進行測試。
可重現建置與 SBOM
如果每次建置都可重現,您就能在日後重新建置舊版本並產生其 SBOM。但多數建置無法重現,因此重新建置,或在今天掃描原始碼,描述的是一次類似的建置,而不是您實際出貨的那一次。能呈現正式環境中有哪些內容的 SBOM,是從產出該版本的 CI 建置中記錄下來的那一份。
即使是可重現建置,也無法取代這份記錄。雜湊值一致只能證明兩次建置產生了相同的輸出;它並不會列出其中納入了什麼。您仍然需要這份資產清冊,以及對其 SBOM 完整性的誠實說明。為什麼 CI 是落實供應鏈安全的地方與 SBOM 最佳實務有更完整的論述。
SLSA 將可重現性視為驗證建置是否如其宣稱般運作的方法之一。
可重現性是團隊透過 Nix、Yocto 或 Debian 的工具等,在自己的建置系統中達成的。CRACI 不會讓建置變得可重現:它會在建置執行時記錄每次建置的 SBOM,因此已出貨內容的記錄不必仰賴重新建置。請參閱建置時 SBOM。