Skip to content

Docker Hardened Images: What the Minimus Shutdown Changes

Docker Hardened Images: What the Minimus Shutdown Changes

I found out Minimus was shutting down the way I find out about most infrastructure news: someone in a Slack group posted “welp” and a link. On October 22 their registry goes dark. Anything still pulling from reg.mini.dev after that date gets whatever it already cached, frozen in time, quietly collecting CVEs the way my downloads folder collects screenshots.

I don’t run Minimus images. I still spent an evening reading the migration docs, because this shutdown is a live answer to a question clients ask me more often than you’d expect: are hardened images actually worth it, or is this security theater with a subscription fee? Watching a hardened-image vendor wind down in real time tells you a lot about both halves of that question. The short version: Docker Hardened Images now has a free catalog that’s hard to argue with, the DIY route is still respectable, and the real lesson here is about vendor risk, not CVE counts.

What “hardened” actually means here

A hardened image is a base image with almost everything removed. No shell. No package manager. No curl, no bash, none of the hundred-odd Debian packages that ride along in a standard node or python image without you ever asking for them. Fewer packages means fewer things a scanner can flag and fewer things an attacker can use once they’re inside your container.

The vendors layer more on top of that: they build packages from source, patch fast when a CVE lands, and ship each image with an SBOM, build provenance, and a cryptographic signature so you can prove what you’re running. That last part matters less for a two-person agency and a lot for anyone filling out a SOC 2 questionnaire.

People sometimes read “hardened images” and hear “Docker is unsafe.” That’s the wrong frame. The runtime is fine for most threat models. The problem is what’s inside your base image. Run a scanner against a stock node:22 image sometime; the CVE list is long, and almost none of it is code you use. It’s inherited surface area. Hardening is mostly the art of not shipping software you never needed.

The Minimus timeline, if you’re running their images

Here’s the situation, per Minimus’s own notice and Docker’s follow-up post. Minimus announced in late August that it’s ending operations. A 60-day maintenance window started on August 24, during which images keep getting upstream updates and bugs still get fixed. On October 22, 2026 the registry shuts off. Images you’ve already pulled keep running after that, but they never get patched again. Every CVE published after October 22 is yours to keep.

That last sentence is the whole reason to act now rather than in November. A frozen hardened image slowly stops being hardened. Six months of unpatched openssl in a “secure” base is worse than a stock Debian image someone actually updates, because the label makes you complacent.

Docker is offering free migration help to Minimus customers, including a human at [email protected] who will go through your image list with you. Whatever you migrate to, and Docker says this themselves, start while the maintenance window still has your current images patched. Deadline-driven migrations done after the deadline are a genre I know well, and it never goes the way anyone hoped.

What’s free in Docker Hardened Images, and what isn’t

This is the part that surprised me when I checked the current state of it. The DHI catalog is free under Apache 2.0, production use allowed, no user caps. Around 4,000 images, with Alpine and Debian compatible variants, so your existing Dockerfiles mostly keep working. Each image ships with near-zero CVEs, a full SBOM, SLSA Build Level 3 provenance, and signatures. When Docker launched DHI it read like an enterprise upsell product. The free tier as it stands today covers what a solo developer or a small agency actually needs.

So what does the paid tier buy? SLA-backed CVE remediation, FIPS and STIG variants, custom image builds, and up to five years of security coverage for software past its end of life. If none of those words appear in your contracts, you probably don’t need the paid tier. If “FIPS” does appear in your contracts, you already knew that.

The obvious comparison is Chainguard, which pioneered this category. Chainguard’s free images only track the latest version of each package; the moment you need to pin a specific older version, you’re on a paid plan. That bit me once during a rollback, and it’s the main practical difference I’d weigh. DHI’s free catalog is more permissive about how you use it. Chainguard’s Wolfi base is arguably the more rigorous engineering project. For client work where I can’t control the budget, free-with-version-tags wins.

The swap is mostly one line, with caveats

DHI works by mirroring the image you want into your own namespace on Docker Hub, then pulling from there. For most services the entire migration is the FROM line. Before, a typical Node service:

FROM node:22

WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

After, with the hardened base mirrored into your org:

FROM myorg/dhi-node:22

WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

The caveats are where your afternoon goes. Hardened images run as a non-root user by default, so anything writing to / or binding port 80 inside the container breaks. There’s no shell, so docker exec -it app bash stops working and you learn to love docker debug or a sidecar. And if your build stage runs apt-get install, that needs to move into a build stage based on a fatter image, because the hardened runtime image has no package manager on purpose. Docker’s migration guide walks through all of these, and it’s honest about the sharp edges.

None of these caveats are DHI-specific. They’re the cost of minimal images generally, and they’re one-time costs. You pay them once and every deploy afterward ships less stuff.

The DIY route still works

Before hardened-image vendors existed, we did this by hand with multi-stage builds and Google’s distroless images, and that approach hasn’t stopped working. Build in a full-fat image, copy the artifact into a minimal runtime:

FROM golang:1.25 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /bin/app ./cmd/app

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /bin/app /app
ENTRYPOINT ["/app"]

That runtime image is a few megabytes and has next to nothing in it to scan or attack. I wrote up how multi-stage builds took a 1.2GB image I was shipping down to almost nothing, and everything in that post still applies.

What DIY doesn’t get you is the maintenance treadmill. Nobody rebuilds your distroless-based image when a base CVE lands unless your CI does, which means you need scheduled rebuilds and a scanner in the pipeline. It also doesn’t get you signed SBOMs and provenance attestations unless you wire up the tooling yourself, which is a weekend the first time and a chore forever after. DIY is cheaper in dollars and more expensive in attention. For a Go binary with no runtime deps, that trade is easy. For a Python service with forty transitive dependencies, it isn’t.

How I’d decide

For side projects and internal tools, I’d stay with multi-stage builds onto alpine or distroless and not think about it further. The vendor question doesn’t deserve headspace at that scale.

For client production work, DHI’s free catalog is my new default recommendation, and that’s an update; a year ago I would have said “alpine plus discipline.” The free tier removed my main objection, and the Minimus shutdown removed my second one in a strange way: watching Docker absorb a competitor’s customers with free migration support tells me this category now consolidates toward the vendor most likely to still exist in five years. Betting client infrastructure on a security startup’s runway is exactly the kind of risk I get paid to notice; it’s a recurring theme in the infrastructure work I do for clients.

For anything with compliance requirements, the decision was never really yours. The framework decides, and you buy whichever paid tier matches the acronyms in your audit.

The thing I’d caution against is the fourth option, which is what Minimus customers who ignore the deadline get by default: a hardened image nobody maintains. That’s the worst of every world. Pick any of the three real options over that one.

Here’s the concrete thing to do this week: run docker scout cves or Trivy against the image you deploy most often, and look at how many findings come from your base versus your own layers. If it’s mostly inherited, swap the base. That’s an hour of work, it’s free, and it will fix more scanner findings than the rest of your backlog combined. And if any of your FROM lines mention reg.mini.dev, you have until October 22. Don’t spend it reading blog posts.