Cloud Native 21 min read

Multi‑Stage Docker Builds & SBOM: Shrink Images and Meet Security Compliance

This guide shows how to dramatically reduce container image size using Docker multi‑stage builds, choose minimal base images, automatically generate SPDX/CycloneDX SBOMs, sign images with Cosign, and integrate the whole process into CI/CD pipelines for secure, lightweight deployments.

Raymond Ops
Raymond Ops
Raymond Ops
Multi‑Stage Docker Builds & SBOM: Shrink Images and Meet Security Compliance

Overview

The article starts with a real‑world problem: a Go micro‑service Docker image built from ubuntu:latest grew to 1.2 GB, causing slow pulls, long deployments, and a large attack surface. It then links image bloat to the rising importance of software supply‑chain security (e.g., Log4j, SolarWinds) and the US Executive Order 14028 that mandates SBOM generation.

Technical Features

Multi‑stage builds : Separate build and runtime stages with FROM golang:1.22‑alpine AS builder and FROM gcr.io/distroless/static-debian12:nonroot (or scratch).

Minimal base images : Use scratch, distroless, or alpine to keep only required libraries.

SBOM generation : syft and trivy produce SPDX or CycloneDX documents, which can be attached to the image.

Image signing : cosign signs the image and attaches the SBOM for supply‑chain integrity.

CI/CD integration : GitHub Actions workflow demonstrates building, tagging, SBOM creation, signing, and vulnerability scanning.

Step‑by‑Step Process

Analyze the existing image with docker images, docker history, or dive to locate large layers (build tools, dev dependencies, caches, docs).

Enable BuildKit ( export DOCKER_BUILDKIT=1) for efficient caching and parallelism.

Create a Dockerfile with multiple FROM statements, copy only go.mod, go.sum, and compiled binaries, and strip debug symbols ( -ldflags="-w -s").

Choose a minimal runtime image ( scratch for static binaries, distroless for glibc‑based languages, or alpine when a shell is required).

Build the image: DOCKER_BUILDKIT=1 docker build -t myapp:1.0 . Generate an SBOM: syft myapp:1.0 -o spdx-json > sbom-spdx.json Scan for vulnerabilities: trivy image --severity HIGH,CRITICAL myapp:1.0 Sign the image and attach the SBOM:

cosign sign --yes myregistry/myapp@sha256:…
cosign attach sbom --sbom sbom-spdx.json myregistry/myapp@sha256:…

Integrate all steps into a CI workflow (see the provided .github/workflows/docker-build.yml example).

Use Cases

Go micro‑service : Reduced image size from 1.1 GB to ~12 MB, pull time from 45 s to 2 s, and eliminated 127 high‑severity CVEs.

React front‑end : Switched from a 850 MB Node image to a 25 MB Nginx‑alpine image, halving build time and cutting high‑severity vulnerabilities from 45 to 2.

Best Practices & Pitfalls

Use a .dockerignore to exclude source control files, docs, and caches.

Combine related RUN commands to reduce layer count.

Pin base‑image versions (avoid :latest).

When using scratch or distroless, ensure the binary is fully static and copy required certificates or timezone data.

Validate SBOM format (SPDX or CycloneDX) and verify it matches the signed image.

Troubleshooting & Monitoring

Common issues include missing libraries in scratch images, container exit codes, DNS failures, and permission problems when copying files across stages. The article provides diagnostic commands ( docker logs, docker inspect, dive) and remediation steps.

Performance metrics (image size, build time, SBOM component count, high‑severity vulnerabilities) can be tracked with simple time measurements, docker images --format, and BuildKit metadata files. Automated CI checks can enforce size limits and vulnerability thresholds.

Conclusion

By combining multi‑stage Docker builds, minimal base images, automated SBOM generation, and Cosign signing, teams can achieve up to 99 % image size reduction, faster deployments, and compliance with emerging supply‑chain security regulations.

Dockerimage-optimizationDevOpssecuritysbommultistage-buildcosign
Raymond Ops
Written by

Raymond Ops

Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.