SBOM
Docker SBOM:如何產生,以及會遺漏什麼
您只需一道指令就能取得 Docker 映像檔的 SBOM:在建置時使用 BuildKit,或在事後使用 Docker Scout 或 Syft。每種做法都會讀取它在映像檔中找到的套件中繼資料。就中繼資料所及的範圍而言,這是映像檔內容的正確紀錄,但它並不是映像檔如何建置的紀錄。
更新日期
如何為 Docker 映像檔產生 SBOM
常見的做法有三種。BuildKit 可以在建置映像檔時寫出 SBOM,並以證明(attestation)的形式附加到映像檔上。Docker Scout 與 Syft 則從已存在的映像檔產生 SBOM,不論映像檔在本機或登錄庫中。
在建置時使用 BuildKit
將 --sbom=true(或其完整形式 --attest type=sbom)加到 docker buildx build。BuildKit 會對建置結果執行其 Syft 掃描外掛,並將 SBOM 以 SPDX JSON 文件的形式附加到映像檔上。若想在推送任何內容前先查看 SBOM,請使用 local 匯出器進行建置:
# Build the image, attach an SBOM attestation and push it
docker buildx build --sbom=true -t registry.example.com/app:1.0 --push .
# The long form of the same option
docker buildx build --attest type=sbom -t registry.example.com/app:1.0 --push .
# Check the SBOM before pushing: write the build result to ./out
docker buildx build --sbom=true --output type=local,dest=out .
# out/sbom.spdx.json is the SBOM 讀取附加在映像檔上的 SBOM
docker buildx imagetools inspect 會從登錄庫讀回證明。所有與 SBOM 相關的內容,都位於其 Go 範本中的 .SBOM 之下:
# Print the SPDX document attached to the image
docker buildx imagetools inspect registry.example.com/app:1.0 \
--format "{{ json .SBOM.SPDX }}"
# List each package and its version
docker buildx imagetools inspect registry.example.com/app:1.0 \
--format "{{ range .SBOM.SPDX.packages }}{{ .name }}@{{ .versionInfo }}{{ println }}{{ end }}" 從現有映像檔產生,使用 Docker Scout
docker scout sbom 會在映像檔有 SBOM 證明時使用該證明;沒有時,則自行為映像檔內容建立索引。它預設輸出 JSON,並可使用 --output 寫入檔案:
# List the packages in an image
docker scout sbom --format list registry.example.com/app:1.0
# Write an SPDX or CycloneDX SBOM to a file
docker scout sbom --format spdx --output app.spdx.json registry.example.com/app:1.0
docker scout sbom --format cyclonedx --output app.cdx.json registry.example.com/app:1.0 從現有映像檔產生,使用 Syft
Syft 是 BuildKit 外掛所採用的開源掃描工具。將它指向映像檔,並以 -o 選擇格式。加上 =file 即可將每種格式寫入各自的檔案:
# CycloneDX JSON to the terminal
syft registry.example.com/app:1.0 -o cyclonedx-json
# Both formats, each to its own file
syft registry.example.com/app:1.0 -o spdx-json=app.spdx.json -o cyclonedx-json=app.cdx.json SPDX 還是 CycloneDX?
BuildKit 證明一律採用 SPDX。Docker Scout 可輸出 SPDX 或 CycloneDX,Syft 則兩者皆可輸出,另外還支援其他格式。兩種標準都會列出套件、版本、授權與套件 URL,因此選擇通常取決於接下來要讀取 SBOM 的工具。差異請參閱CycloneDX 與 SPDX 比較。
映像檔掃描工具如何建立 SBOM
這些工具的運作方式都相同:解開映像檔的各層,讀取其中找到的套件中繼資料,也就是作業系統的套件資料庫,以及語言套件管理工具留下的中繼資料。每個能被識別的套件都會成為一筆 SBOM 項目,包括來自基礎映像檔的套件。
納入建置階段與建置內容
BuildKit 預設只掃描最後一個階段。在多階段建置中,先前階段所用的編譯器、建置工具與套件並不在最終映像檔中,因此也不會出現在其 SBOM 裡。Docker 的 SBOM 證明文件說明了兩個可擴大掃描範圍的建置參數。BUILDKIT_SBOM_SCAN_STAGE 可加入某個階段,BUILDKIT_SBOM_SCAN_CONTEXT 則可加入建置內容(build context):
# syntax=docker/dockerfile:1
# Scan the build context as well as the image
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
FROM golang:1.25 AS build
# Include this build stage in the SBOM
ARG BUILDKIT_SBOM_SCAN_STAGE=true
WORKDIR /src
COPY . .
RUN go build -o /out/app .
FROM scratch
COPY --from=build /out/app /app
ENTRYPOINT ["/app"] 兩者都必須在 Dockerfile 中以 ARG 宣告。只用 --build-arg 設定並不會生效,不過 --build-arg 可以覆寫 Dockerfile 已宣告的值。使用 local 匯出器時,每個被掃描的階段都會有自己的檔案,例如 sbom-build.spdx.json 與 sbom.spdx.json 並列。
掃描仍會遺漏什麼
階段掃描補上了一個缺口。但掃描工具讀取的仍然是檔案,而建置所使用的某些內容不會留下檔案,或留下的檔案無法被識別:
- 沒有套件中繼資料的檔案。以
curl下載的二進位檔、在RUN步驟中解開的 tarball,或複製進來的內嵌程式碼。有些二進位檔(例如 Go 二進位檔)帶有掃描工具可讀取的建置資訊,但許多並沒有。 - 建置下載後又刪除的內容。
RUN步驟在同一層中取得、使用並移除的套件或安裝程式,不會在檔案系統上留下任何可供掃描工具讀取的東西,無論是否為最後階段。 - 內容是如何進來的。掃描產生的 SBOM 列出存在的內容,但不會說明套件來自哪個登錄庫或主機,也不會說明是哪個步驟取得的。
- 您未標記的階段。階段掃描須主動啟用,可按階段或全域設定。未加上參數的階段仍會被排除。
- 掃描設定。出現哪些內容取決於掃描工具的執行方式。在某個專案中,單一個 Syft 旗標就決定了 npm 套件是否會出現在結果中。
Yocto 建置中的相同問題,請參閱為什麼 SBOM 掃描工具會遺漏 Yocto 建置中的內容。
為什麼這很重要
遭入侵的建置工具或基礎映像檔,即使從未出現在最終映像檔中,也會影響您出貨的內容。而沒有中繼資料的二進位檔,可能帶有沒有任何 SBOM 項目指向的漏洞。資安公告發布時,您不只需要知道映像檔裡有什麼,也需要知道建置映像檔時用了什麼。
同時記錄建置
映像檔 SBOM 回答的是映像檔裡有什麼。建置紀錄回答的是建置引入了什麼:它拉取的基礎映像檔,以及每個步驟取得的套件,包括沒有任何 lockfile 列出的隱藏相依套件。CRACI 會在您的 GitHub Actions 作業執行時,透過執行器上可辨識套件的代理伺服器記錄這些內容,API 則會回傳該作業的 SBOM、網路追蹤與來源證明。以映像檔 SBOM 說明您出貨的內容,以建置紀錄說明它是如何產生的。
請參閱SBOM 工具比較、建置時 SBOM,以及如何在 GitHub Actions 中產生 SBOM。
Docker SBOM 常見問題
如何為 Docker 映像檔產生 SBOM?
常見做法有三種。將 --sbom=true 加到 docker buildx build,BuildKit 就會將 SPDX SBOM 附加到映像檔上。對現有映像檔執行 docker scout sbom。或執行 Syft,例如 syft IMAGE -o cyclonedx-json。三者都會讀取它們在映像檔中找到的套件。
什麼是 SBOM 掃描工具?
一種讀取檔案(例如原始碼目錄、lockfile 或容器映像檔),並針對其能識別的套件寫出 SBOM 的工具。Syft、Trivy、Docker Scout 與 BuildKit 的 Syft 外掛都是 SBOM 掃描工具。它們描述的是眼前的檔案,而不是產生這些檔案的建置。
Docker 會產生哪種 SBOM 格式?
BuildKit 證明是附加在映像檔上的 SPDX JSON 文件。Docker Scout 可以輸出套件清單,或寫出 SPDX 或 CycloneDX。Syft 兩者皆可輸出,還支援更多格式。請選擇使用該 SBOM 的工具所預期的格式。
掃描工具如何從 Docker 映像檔建立 SBOM?
它會解開映像檔的各層,讀取其中找到的套件中繼資料:作業系統的套件資料庫,以及語言套件檔案,例如已安裝的 npm 或 Python 套件中繼資料。每個能被識別的套件都會成為 SBOM 中的一筆項目。
映像檔 SBOM 為什麼會遺漏元件?
因為它只能列出在所讀取的檔案中能識別的內容。以 curl 下載的二進位檔沒有套件中繼資料,建置步驟下載後又刪除的套件不會留下任何可讀取的東西,而除非您啟用階段掃描,先前的建置階段也會被排除。
映像檔 SBOM 還有用嗎?
有用。它是您出貨映像檔內容的正確紀錄,包括來自基礎映像檔的套件。只是它不描述映像檔如何建置,因此在這點很重要時,請搭配建置紀錄使用。