Docker BuildKit SBOM Tricks

Docker BuildKit SBOM Tricks
Photo by Reproductive Health Supplies Coalition / Unsplash

By default the sbom produced from an image only includes dependencies from the final image. This can be inaccurate for some builds, like a frontend static app whose final image would only include bundled js in an nginx image. Here's an example Dockerfile for an SSR SvelteKit application, note the 3rd line ARG BUILDKIT_SBOM_SCAN_STAGE=true which tells BuildKit to produce an sbom for the stage.

# Build
FROM node:18-alpine AS build
ARG BUILDKIT_SBOM_SCAN_STAGE=true
WORKDIR /app
COPY ./package.json ./yarn.lock ./
RUN yarn install --immutable --ignore-scripts
COPY . .
RUN yarn build

# Runtime
FROM node:18-alpine AS runtime
USER node:node
WORKDIR /app
COPY --from=build /app/package.json /app/entrypoint.js /app/build ./
EXPOSE 3000
CMD ["./entrypoint.js"]

To produce sboms add the --sbom=true option to the build command

# build
docker buildx build --sbom=true -t cotyhamilton/budgety .

# verify by saving filesystem to disk and browsing the spdx files
docker buildx build --sbom=true -t cotyhamilton/budgety -out ./image .

The above information can be found https://www.docker.com/blog/generate-sboms-with-buildkit/ and https://docs.docker.com/build/attestations/sbom/. Here's the method to get the sbom from an image.

docker buildx imagetools inspect ghcr.io/cotyhamilton/budgety:1_2023-10-03.59.1 --format "{{ json .SBOM.SPDX }}"

To get additional sboms, like from our build stage, and from multi-platform images, it's not as straightforward (especially for me, I have no idea what go templating is 😜). Here are some format templates:

# get all sboms
docker buildx imagetools inspect ghcr.io/cotyhamilton/budgety:1_2023-10-03.59.1 \
	--format '{{ json .SBOM }}'

# get the additional sboms of the linux/amd64 image
docker buildx imagetools inspect ghcr.io/cotyhamilton/budgety:1_2023-10-03.59.1 \
	--format '{{ json (index .SBOM "linux/amd64").AdditionalSPDXs }}'

# get the additional sbom of the linux/amd64 image that is named sbom-build
docker buildx imagetools inspect ghcr.io/cotyhamilton/budgety:1_2023-10-03.59.1 \
	--format '{{ range (index .SBOM "linux/amd64").AdditionalSPDXs }}{{if eq .name "sbom-build"}}{{ json . }}{{ end }}{{ end }}'
    
# print the packages in the above sbom in a human readable format (name@version)
docker buildx imagetools inspect ghcr.io/cotyhamilton/budgety:1_2023-10-03.59.1 \
	--format '{{ range (index .SBOM "linux/amd64").AdditionalSPDXs }}{{if eq .name "sbom-build"}}{{range .packages}}{{.name}}@{{ .versionInfo }}{{"\n"}}{{end}}{{end}}{{end}}'