Docker Engine 29 changed a default that looks boring until it lands on a small host.

For fresh installs, Docker now uses the containerd image store by default. That sounds like backend plumbing. The part operators noticed on Reddit is simpler: Docker's own docs say this mode uses more disk space, keeps images in both compressed and uncompressed forms, and makes the old overlay2 data stay on disk but disappear from view when you switch.

That is why the hot r/selfhosted thread matters. The headline is not "Docker adopted containerd." The real story is that Docker is starting to favor newer OCI-era capabilities over the old assumption that the local engine should be as storage-thrifty and backwards-familiar as possible.

What is actually verified

Docker's documentation is clear on the main mechanics.

The containerd image store page says it is the default storage backend for Docker Engine 29.0 and later on fresh installations. Upgraded daemons do not flip automatically. They continue using the legacy graph drivers, including overlay2, until the operator enables the containerd image store.

The same page also states that the containerd image store uses more disk space than the legacy drivers for the same images because it stores both compressed and uncompressed formats. Docker goes further than that. It says the difference becomes more noticeable when multiple images share the same base layers: with the legacy store, those shared base layers were stored once locally, while with containerd each image keeps its own compressed copy of shared layers even though the uncompressed layers are still deduplicated through snapshotters.

Another detail matters operationally. When you enable the containerd image store, existing images and containers from overlay2 remain on disk but become hidden. Docker's docs explicitly say they reappear if you switch back. In other words, this is not a clean in-place swap. It is a storage-backend fork with a visibility toggle.

Docker's release notes for v29 also flag the change in plainer upgrade language. The release notes warn that the release includes breaking changes and deprecations, then note that the containerd image store is now the default for fresh installs.

Why Docker is doing this anyway

Docker is not taking this hit for no reason.

The same docs page lists the features the classic store could not handle cleanly: local multi-platform images, image attestations such as provenance and SBOM data, Wasm workloads, and pluggable snapshotters for things like lazy pulling and alternate distribution paths. Those are not side quests. They line up with where container tooling has been heading for a while.

So this is less a random regression than a choice about what Docker now treats as the normal case. Modern image metadata, multi-arch work, and new snapshotter behavior are moving from specialist features toward default-engine assumptions. The trade is that local disk behavior gets worse before it gets better.

The public evidence that this is not just one confused Reddit post

The Reddit thread did have the usual first-round skepticism. One commenter asked where the duplication claim came from. Another user pointed straight back to Docker's docs, quoting the section about shared base layers and compressed copies.

More useful than the back-and-forth was the operator experience in the same thread. One commenter said they ran out of disk space that day because of this. Another said they had already hit problems on ZFS-backed hosts and ended up explicitly disabling the containerd-snapshotter feature in daemon.json.

There is also a matching GitHub issue trail.

In moby/moby issue #51579, a user reported losing 6 GB of available /var storage after moving to a fresh Docker 29 installation. The issue includes docker system df --verbose output showing image unique sizes roughly doubling or tripling compared with Docker 28 or with Docker 29 when the containerd-snapshotter feature is disabled. That does not prove every host will see the same multiplier, but it does show the disk-cost complaint is grounded in more than one anecdote.

Another open issue, #52411, reports docker pull failures on Docker 29.4.0 when using the containerd snapshotter, with the same image pulling successfully when the feature is disabled. That is a separate bug, not proof that the whole migration is broken, but it does reinforce the broader point: this default shift is still carrying migration and compatibility edges.

What makes this interesting beyond one release note

The usual way to read a change like this is, "Docker moved one layer lower in the stack." That is true and also incomplete.

What actually happened is that Docker made a bet about which costs matter more.

The classic local image store was easier to reason about for people running a handful of servers, lab boxes, or storage-constrained hosts. The newer path matches the container ecosystem Docker now has to live in: OCI artifacts with attestations, multi-platform images, alternative snapshotters, and a world where containerd is not just an implementation detail.

That is a sensible direction if you are optimizing for feature parity with the broader OCI stack.

It is a less comfortable direction if you are the person who just upgraded a practical host and found hidden old layers, fatter unique-size numbers, or a full partition.

That gap is the story. The container ecosystem keeps shipping supply-chain and portability features as if local resources are cheap and operational cleanup is someone else's job. The self-hosted crowd notices first because they are the ones staring directly at /var.

What remains uncertain

A few limits matter here.

First, this is not an automatic upgrade surprise for every existing Docker host. Docker's docs say the new backend is the default for fresh installs. Older hosts keep using legacy graph drivers until the operator opts in.

Second, the severity of the disk hit will vary. Docker documents higher space usage as a design consequence, but the exact penalty depends on image mix, shared layers, and whether you are comparing logical image accounting or raw on-disk state.

Third, some of the public bug reports are still open. They are useful evidence of rough edges, not final proof of root cause across all environments.

Practical takeaway

If you are deploying fresh Docker 29 hosts, stop assuming the old image-store behavior still applies. Check disk growth early, especially on small VPSes, homelab boxes, and anything with lots of images sharing a common base.

If you are planning to enable the containerd image store on upgraded hosts, read the migration notes carefully. Old overlay2 data can remain on disk while vanishing from the active view, which is a nice way to lose track of capacity.

And if you rely on a storage setup or registry workflow that is already a little unusual, treat this change like a real migration, not a harmless default flip.

The Reddit thread got attention because people saw a storage problem. The more important point is that Docker's defaults are now being shaped by the OCI future, not by the habits that made the old local engine feel simple.

Sources

  • Reddit: https://old.reddit.com/r/selfhosted/comments/1t4otpu/docker_engine_29_has_changed_the_default_image/
  • Docker docs, containerd image store: https://docs.docker.com/engine/storage/containerd/
  • Docker Engine 29 release notes: https://docs.docker.com/engine/release-notes/29/
  • Moby issue #51579, bloated image unique sizes: https://github.com/moby/moby/issues/51579
  • Moby issue #52411, pull failures with containerd snapshotter: https://github.com/moby/moby/issues/52411