Generate an SBOM for the final image, list the OS packages and libraries, and mark anything not needed at runtime, such as compilers, package managers and debug tools. Then use a multi-stage build so those stay in the build stage and only the artifacts you need reach the final image.
Why smaller is a security gain
Every package in an image is something that can match an advisory. Build tools and shells are useful during the build and rarely needed afterwards. Removing them cuts the number of findings and the places an attacker could use. It also makes the SBOM shorter to review.
Step 1: get the real inventory
Generate the SBOM from the built image, not just the Dockerfile, so you see base layers too. If you only look at the application's lockfile you will miss OS packages. See what a container image SBOM contains and misses.
Step 2: sort components into three groups
| Group | Examples | Action |
|---|---|---|
| Needed at runtime | Application libraries, runtime, certificates | Keep |
| Needed only to build | Compilers, headers, package managers | Move to a build stage |
| Not needed at all | Editors, network debugging tools, docs | Remove |
Be careful with the first group. A missing shared library crashes the container, so confirm by running it.
Step 3: use multi-stage builds
Docker's documentation describes multi-stage builds: you use multiple FROM statements in a Dockerfile, each can use a different base, and each begins a new stage. You can selectively copy artifacts from one stage to another, leaving behind everything you do not want in the final image.
A sketch:
FROM build-image AS build
WORKDIR /src
COPY . .
RUN make
FROM runtime-image
COPY --from=build /src/app /app
CMD ["/app"]
The first stage holds the compiler and sources. The final stage holds only the binary and what the runtime base provides.
Step 4: compare SBOMs
Generate the SBOM again for the new image and diff the two. The removed components list is your evidence. Check that nothing you needed disappeared, by running your tests and a smoke check against the new image.
Step 5: keep it that way
Add a check to CI that flags new packages in the final image. A shell or compiler that sneaks back in deserves a question. For stage questions, read which stage is scanned in a multi-stage build.
What an SBOM will not decide
It cannot tell you whether a package is used at runtime. Treat the list as candidates and test.
Try it yourself
Click through it at your own pace, or open it full screen. Look at the OS package findings and ask which ones the app really needs.
Safeguard scans container images and produces SBOMs, so you can compare before and after. A free scan is a quick way to start.
Quick check
Does a smaller image mean no vulnerabilities?
No. It means fewer places for them to hide. The remaining packages still need scanning.
Should I scan the build stage too?
Build stages can matter for supply chain risk, but findings in the final image are what ships.
Sources
Last reviewed: 19 October 2026.