Alpine vs Debian vs Ubuntu: does your base image change container isolation?¶
Search "alpine vs debian" or "is alpine more secure" and you get a hundred posts arguing about package counts and CVE surface. Those are real questions. But they answer a different question than the one most people are actually asking, which is: if I run untrusted code in this container, how much isolation stands between that code and my host?
That is a containment question, not a base-image question. So we measured it.
We ran ironctl scan over the seven
most-pulled base OS images in their default docker run configuration and
graded each 0 to 100 on how contained it is.
The result is the same number, seven times.
The scores¶
| Base image | Isolation score | Grade |
|---|---|---|
alpine:3.21 |
48 | D |
debian:12-slim |
48 | D |
ubuntu:24.04 |
48 | D |
busybox:1.37 |
48 | D |
amazonlinux |
48 | D |
rockylinux |
48 | D |
fedora |
48 | D |
Not close-together. Identical. And it is not just the total: the per-dimension breakdown is byte-for-byte the same across all seven.
| Dimension | alpine | debian | ubuntu | Max |
|---|---|---|---|---|
| Non-root user | 0 | 0 | 0 | 15 |
| Dropped capabilities | 4 | 4 | 4 | 20 |
| Seccomp profile | 15 | 15 | 15 | 15 |
| Network isolation / egress | 4 | 4 | 4 | 15 |
| Read-only root filesystem | 0 | 0 | 0 | 10 |
| No docker.sock exposure | 15 | 15 | 15 | 15 |
| No shared host namespaces | 10 | 10 | 10 | 10 |
| Total | 48 | 48 | 48 | 100 |
Why they tie¶
Isolation is a property of how you run the container, not of what is inside the
image. ironctl scan grades the runtime posture the container gets from the host:
which capabilities it keeps, whether it runs as root, whether the root filesystem
is writable, whether egress is open. None of those are decided by whether the
userland was assembled from Alpine's apk or Debian's apt.
Every one of these images ships the same way by default: root user (uid 0), full default capability set, writable root filesystem, open egress on the default bridge. That is why they all land on 48. The base image you pick changes your CVE surface and your image size. It does not, on its own, change your blast radius when code inside the container turns hostile.
This does not mean Alpine and Debian are interchangeable. A smaller userland with fewer packages means fewer things to patch, and that is a legitimate reason to prefer a minimal base. But "fewer packages" is a supply-chain argument, not a containment one. If you switch base images expecting a stronger boundary and change nothing else, the boundary is exactly as strong as it was.
What actually moves the number¶
The same handful of docker run flags takes every one of these images from 48 to
a clean 100 out of 100, grade A, without changing the base image at all:
docker run -d \
--user 65532:65532 \
--cap-drop=ALL \
--security-opt=no-new-privileges \
--read-only --tmpfs /tmp \
--network=none \
alpine:3.21
Swap alpine:3.21 for debian:12-slim or ubuntu:24.04 and the score is still
100. The flags are what carry the grade, not the image. ironctl scan --fix writes
this stanza for you from any failing scan.
The honest takeaway¶
If your question is "which base image is more isolated," the data says: none of them, by default, and they are tied. Pick your base image for size, package freshness, and CVE surface. Then earn your isolation separately, with runtime flags, and verify it with a number instead of a vibe.
See where your images land¶
Every image above has a per-dimension scorecard with the exact flags that close each gap. Browse the full interactive ranking across 151 images, filter by category, and grab a copy-paste score badge for your own repo at the Container Isolation Scores explorer. The leaderboard refreshes weekly.
Scan the image you actually run in about ten seconds: