
Containers are now mainstream production infrastructure, so the contents of your runtime images matter more than ever. In CNCF’s Cloud Native 2024 report (published March 2025), 91% of organisations said they use containers in production in 2024, and the reported average container count rose to 2,341 (up from 1,140 in 2023), which is a lot of artefacts to keep tidy, patchable and explainable.
That scale changes the feel of container work. You might be responsible for one service, but you’re also part of a bigger system where small build decisions multiply fast. When a base image choice adds extra packages, you don’t just inherit them once; you inherit them across rebuilds, across services and across every environment that needs to stay consistent.
This article gives you a straightforward model you can apply without drama: build with a tool-rich stage, ship with a tool-lean stage, then add a couple of safety rails so things keep working as your tooling and dependencies change. The facts here come from two places you can trust and verify yourself:
- CNCF’s annual survey data for what’s happening in production at scale, and
- The official distroless project documentation for what distroless images are, how to build them and the common gotchas.
If you’re exploring practical approaches to open source container security, this same model fits naturally because it focuses on reducing what you ship and tightening what you can verify.
If you’ve ever looked at a container and thought, why is all of this in here, you’re already thinking in the right direction.
Less Stuff With More Signal
Distroless images are defined very plainly by the distroless project:
- They contain only your application and its runtime dependencies
- They don’t include package managers, shells or the extra programs you’d expect in a typical Linux distribution.
That isn’t a philosophical stance; it’s a practical boundary that nudges production images toward doing one job, reliably.
The easiest way to appreciate the intent is to look at the project’s own size benchmark. You don’t need to chase tiny numbers for their own sake, but size often correlates with fewer components to track and fewer places for surprises to hide.
What I like about this approach is how it changes the conversation inside a team. Instead of asking, which distro should we use for our production container, you start asking, what does the service truly need at runtime, and what belongs in the build pipeline. That’s a healthier question because it leads to decisions you can automate, review and repeat.
A minimal runtime image gives you sharper feedback. When the container doesn’t contain a kitchen sink of tooling, your build pipeline, your dependency choices and your release discipline become more visible, and that’s where you actually have leverage. It also makes it harder to fall into the habit of fixing production problems by improvising inside the container, which can feel productive in the moment but tends to leave weak spots later.

There’s a second benefit too: minimal images reduce the number of moving parts you have to keep in your head. When something breaks, you’re not wondering which package manager state you’re in, or which tool version got baked into the image last month. You’re pushed toward reproducible fixes, which are kinder to the next person on call.
Two Images, One Steady Workflow
A lot of teams get stuck on an unhelpful question: do we want a minimal image, or do we want a convenient one? You can have both, as long as you separate building from running.
Distroless documentation directly recommends Docker multi-stage builds and describes the basic idea: one stage builds your application artefacts, then you insert those artefacts into your runtime distroless image. This model scales across languages because you’re not trying to make a single image serve every purpose.
In practice, you end up with a dev-and-prod pairing. Your build stage can include compilers, package managers, test tools and whatever makes development productive. Your final stage is the production runtime, designed to hold only what the service needs to start and keep serving.
If you’re used to a single Dockerfile that tries to do everything, this split can feel like extra work at first. Then it starts paying you back. Builds become easier to reason about because the output is explicit: an artefact goes in, a minimal runtime comes out. That clarity matters when container counts are rising, because small efficiencies in build standardisation compound across repositories.
You stop thinking of production containers as tiny servers you can log into, and you start treating them as release artefacts you can reproduce. The subtle win here is consistency. Once your team agrees that production images are for running, not for tinkering, reviews get simpler and incidents get less chaotic.
This doesn’t remove your ability to troubleshoot; it changes where troubleshooting lives. You’ll lean more on repeatable builds, good logging and explicit debugging paths, which is a trade many teams end up preferring once it’s in place.
It also lines up with how container adoption looks at scale. CNCF reports production use of Kubernetes reached 80% in 2024, up from 66% in 2023, which is another signal that container operations are increasingly standardised around repeatable deployment patterns rather than one-off server habits. When Kubernetes is a common denominator, production containers that behave predictably are a genuine advantage.
No Shell and No Surprises
Distroless images don’t include a shell by default, and that one detail explains a lot of the early friction. Your Entrypoint must be specified in vector form (the JSON array form); otherwise, the runtime may try to prefix it with a shell that isn’t there.
This is the kind of issue that can feel mysterious in CI, because your app itself is fine; it’s the container’s startup mechanics that changed. Once you know the rule, it becomes a one-time adjustment you standardise across services. That standardisation matters more than people expect, because entrypoints tend to be copied, tweaked and copied again, and small inconsistencies show up at the worst possible time.
If your production container doesn’t include a shell, then your image definition needs to be honest about that. It shouldn’t rely on shell conveniences, implicit parsing or commands that only work because a shell is present. Vector-form entrypoints are boring, but they’re reliable.
A question worth asking your team, early, while it’s still easy to improve: if nobody could exec into production containers for ad hoc fixes, would your service still be diagnosable from its logs, metrics and a reproducible build?
You don’t have to answer that perfectly on day one. The value is in letting the question guide your choices. It pushes you toward putting configuration in the right place, capturing the right logs and making your builds behave the same way locally, in CI and in production.
Trust and Then Verify
Minimal images help because there’s less inside them, but safer shipping also includes knowing you got the image you think you got. That matters even more when your organisation pulls base images from shared sources, and especially when those sources are public.
Sysdig’s 2024 Cloud-Native Security and Usage Report approaches this with real-world usage data rather than a survey, and its methodology section explains that it draws on analysis across customer environments at scale. In that report, Sysdig says it analysed over 1,400 uniquely named registries spanning more than 2.6 million containers, and found 66% of registries used were public (34% private). Public registries are convenient, and that convenience is exactly why verification steps should be simple enough to do every time.
Verification is a force multiplier for small teams. When you don’t have time to deeply inspect every dependency, you at least want a repeatable way to validate what you’re consuming. That’s not about assuming the worst; it’s about being consistent, every time.
Distroless leans into that practicality. The distroless project states that all distroless images are signed by cosign using ephemeral keys (keyless), and that this is the only supported verification mechanism. Verifying a base image becomes a normal pre-build step, like running tests before you ship.
If you’re new to signing and verification, there’s a reassuring angle here. The project is telling you what the supported path is, and it’s giving you an example to follow. That reduces guesswork, which is often the real barrier to better security practices.
There’s another subtle benefit too. When you verify your base images, you create a stronger line between official inputs and your own application logic. Over time, that can make root-cause analysis faster. You spend less energy wondering whether you started from something unexpected and more energy addressing the actual issue.
Tooling Compatibility and Debug Options
Adopting distroless should feel boring, in the best sense. Two operational details help keep it that way.
First, distroless images changed their format in a way that can trip older tooling. The project documentation states that since March 2023, distroless images use OCI manifests, and it explicitly advises updating container tooling if you see OCI manifest-related errors. This is an easy win, because the fix is usually a tooling upgrade rather than a redesign.
This is one of those details you only have to learn once. After that, you can bake it into your team’s baseline requirements: keep your container tooling current enough to handle OCI manifests, and you avoid a class of failures that have nothing to do with your app code. That kind of reliability pays dividends when you’re supporting multiple services.
Second, minimal doesn’t mean you’ve banned debugging. Distroless provides debug image variants that include a BusyBox shell so you can enter the container when you deliberately choose to do so, and it shows how to run a debug image with a shell entrypoint. That gives you a controlled break-glass approach: keep production images lean by default, and reach for debug variants when you genuinely need a shell.
This matters for adoption because it lowers the emotional cost of change. Teams resist minimal images when they fear losing visibility. Debug variants give you an answer that’s practical and controlled. You still have a tool when you need it, but you stop carrying that tool everywhere, all the time.
At today’s container scale, the win isn’t just a smaller image; it’s a workflow you can keep repeating without accumulating mess. Distroless images give you a clear definition of what belongs in production, multi-stage builds give you a friendly on-ramp and verification plus sensible debug options keep the day-to-day experience practical.
If you want a clean starting point, keep it simple and make it routine:
- Adopt a multi-stage build so your build tools stay out of the final runtime image.
- Use vector-form entrypoints so distroless containers start consistently without relying on a shell.
- Verify base images with the distroless-supported keyless cosign approach before you build on top.
- Keep your container tooling current to avoid OCI manifest compatibility surprises, and use debug variants when you genuinely need a shell.
Do those four things, and you’re not just making images smaller. You’re making your production artefacts easier to explain, easier to reproduce and easier to trust, which is a solid place to be when containers are already widely used in production.
