← Back to list

Docker Has Been Hoarding Your Disk Space for Years

I got 60 GB back — without deleting a single image, container, or volume. Just using a handful of codelines.

Christoph Schweres in rigel-computer.com · 2026-06-22 20:26 · 0 claps · 8.0 min read
#docker #web-development #devops #windows #storage
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval 🌐 · Web Development ☁️ · DevOps & Cloud 🔭 · Astronomy & Space

Docker Has Been Hoarding Your Disk Space for Years

I got 60 GB back — without deleting a single image, container, or volume. Just using a handful of codelines.

AI-generated picture, qouting the “Free Willy”-cinema-theme to metaphoric lead to the issue of the article

AI-generated picture, qouting the “Free Willy”-cinema-theme to metaphoric lead to the issue of the article

An article about saving disk space? Mid-2026? “Storage is cheap!” — yeah, right — until now!

Cue the rude awakening when you go looking for a 32GB DDR5 stick — or a bigger SSD.

So here’s an article about disk space — with a concrete fix to claw some back on your local machine. Including backup: under two hours of work, decent chunk of money saved, and maybe something learned along the way.

What this article is about: Cleaning up a bloated Docker installation on Windows.

In my case: 60 GB back.

Read on — it’s more straightforward than you’d think.

But first (skip ahead if you already know this): a quick word on why storage costs are suddenly a thing again:

“Storage is cheap” — that used to be true. Not anymore.

SSD +90%, DDR5 RAM +300% — since last summer. AI data centers have bought up a huge chunk of the world’s storage production. That’s strategy for them; for everyone else, it’s sticker shock.

Fifteen years of falling prices made all of us a little sloppy. Tools, operating systems, Docker. Why be careful when it costs nothing?

It costs something now — see for yourself:

Sources: 3DCenter.org, TrendForce, Heise.de · Indexed: July 2025 = 100 · Intermediate values interpolated

Sources: 3DCenter.org, TrendForce, Heise.de · Indexed: July 2025 = 100 · Intermediate values interpolated

The problem — and the fix

It started with a question that, not long ago, nobody really needed to ask. Old answer: just buy a bigger drive, run Acronis Disk Clone, done.

New question: where the hell is my disk space actually going?

Sure, things like Hugging Face model weights have started adding up — but those are manageable, and easy enough to offload to an external drive: just keep the weights you actually need locally.

Docker had always been my prime suspect. Dozens of images, running containers, a graveyard of DDEV experiments from years back — but docker system df said everything was fine.

Fine? It was anything but. I started digging: how does Docker actually behave under the hood on Windows, specifically around storage? First stop: check the properties of the AppData\Docker folder.

171 GB.

Why the hell is my AppData folder for Docker suddenly 171 GB? I've been running Docker for over two years, almost daily, with DDEV for local web projects. I knew things would accumulate. But 171 GB? On an SSD that was already running low?

First obvious step:

docker system df

The result was sobering — in a good way:

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          50        23        63.17GB   27.86GB (44%)
Containers      29        22        5.051GB   4.105GB (81%)
Local Volumes   144       3         7.421GB   7.373GB (99%)
Build Cache     324       0         48.38GB   13.89GB

Add up the SIZE column: roughly 124 GB. But the folder on disk was 171 GB. A gap of nearly 47 GB that Docker doesn’t account for anywhere. Hello? What’s up, Doc(ker)?

The culprit: docker_data.vhdx — a file that only ever grows

Anyone running Docker Desktop on Windows with the WSL2 backend — which has been the default for years — is never actually working with Docker directly. In the background, a full Linux environment runs inside a virtual machine, and everything that environment stores lives in a single file: a VHDX, a virtual hard disk.

On my machine, it was here:

C:\Users\<Name>\AppData\Local\Docker\wsl\disk\docker_data.vhdx

And it was exactly the 171 GB the folder size had already suggested. Not a sum of multiple files, not forgotten log archives — one single, massive file.

The mechanism is straightforward: the VHDX grows automatically whenever more space is needed inside. It never shrinks automatically when space is freed. Delete an image, a container, a volume — inside WSL the space is free, but on the Windows side, the file stays at its previous maximum size. Two years of heavy Docker use, and that adds up to a whole lot of… air.

This isn’t a bug. It’s by design. If you never question it — say, until your drive starts filling up — one day it just goes boom, and that next 10 GB Hugging Face model doesn’t fit anymore.

Before touching anything: back up docker_data.vhdx

At this point I wanted to just dive in. But when it’s software I depend on every single day, the move is to slow down and think: how do I get back to a working state if something goes wrong?

First: hit the brakes. The next step modifies a 171 GB file that contains literally everything Docker has — all images, all volumes, all containers.

The rule is simple: WSL has to be completely shut down first. Otherwise the file is in use, and copying it could produce an inconsistent snapshot at best.

wsl --shutdown
wsl --list --verbose

Only when every distro shows “Stopped” in that second command is the file actually free. Then — and only then — make a full copy. Robocopy works fine from an already-open PowerShell:

robocopy "C:\Users\<Name>\AppData\Local\Docker\wsl\disk" "D:\Backup\docker_data_backup" docker_data.vhdx /Z /J

An external drive or a large USB stick is the right destination here. Copying to the same drive that’s already full is both unsafe and kind of missing the point.

At 171 GB, this took an hour and a half. The kind of wait that makes you wonder whether the whole thing is worth it. It is. A backup of this size is the price of modifying a low-level file without having to hold your breath the whole time. If something goes wrong — power cut, hanging process, interrupted write — the copy is your only way back.

Data safety has a cost. Sometimes it’s just time.

Now: actually touching docker_data.vhdx

Step 1: Compact the file

Backup in hand, time for the actual fix.

Windows ships with a built-in tool for exactly this: diskpart. It can address virtual disks like VHDX files directly and physically remove unused empty space from the file.

Quit Docker Desktop completely (right-click the tray icon, “Quit Docker Desktop” — not just closing the window), then make sure WSL is down:

wsl --shutdown

Then open PowerShell as Administrator — required for diskpart - and run:

diskpart
select vdisk file="C:\Users\<Name>\AppData\Local\Docker\wsl\disk\docker_data.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit

Pro tip: open PowerShell directly in the AppData folder where the VHDX lives — saves you typing out that whole path.

Important

This takes a while. On my machine: almost 15 minutes — with zero visible feedback.

No progress bar, no percentage, just a blinking cursor. This is exactly the moment where an impatient person closes the window or hits Ctrl+C, assuming it’s hung. It isn’t. Interrupting a compaction mid-write is how you actually corrupt the file — so:

Leave it alone. Wait it out.

The result genuinely surprised me. The file went from 171 GB to 112 GB. Nearly 60 GB back, without deleting a single image, container, or volume. Pure accumulated air, years in the making.

That’s basically it.

My drive was suddenly showing over 100 GB free again. Mission accomplished.

Start Docker again (just double-click to launch normally, WSL comes up automatically with it) — the bloated ghost is gone.

So what about the standard Docker tool docker builder prune? There were still 13 GB flagged as reclaimable in that docker system df output...

Well, the most intruging findings you have already seen — just read on if your interested in the special topics — no MUST-HAVE, just nice-to-have!

tl;dr — running docker builder prune afterward doesn't free up any additional disk space. Here's why:

Step 2: Taking out the rest of the trash — docker builder prune — good idea, but…

compact vdisk only compresses the file - it doesn't delete anything inside Docker. The actual garbage that docker system df had flagged as "RECLAIMABLE" was still there. The build cache stood out: 48.38 GB total, 13.89 GB marked as reclaimable.

Build cache accumulates with every docker build - intermediate layers that could theoretically be reused, but in fast-moving projects (new composer.json, new package.json, the kind of churn that's constant with DDEV projects) they're often used once and then just sit there.

Once Docker Desktop was running again:

docker builder prune

Without -a - this removes only genuinely unused cache, leaving anything still referenced by active or upcoming builds untouched. Docker tells you exactly how much it's about to remove before you confirm.

Before and after, straight from docker system df:

Before:  Build Cache   324 entries   48.38 GB total   13.89 GB reclaimable
After:   Build Cache   281 entries   34.50 GB total    0 B reclaimable

Exactly 13.88 GB gone — matching what was flagged as reclaimable. 43 cache entries removed, 281 kept because they’re still actively referenced. The right amount of cleanup: tidy without being destructive.

The surprise I didn’t see coming

Here’s the part that actually caught me off guard. The logical next step: shut down WSL again, run diskpart compact again - surely the VHDX would shrink by another 13.88 GB?

Nope. Zero effect. The file stayed exactly at 112 GB.

A quick search showed this isn’t a one-off. A Docker bug tracker thread describes exactly the same behavior — prune done, diskpart compact run, no change in file size, despite internal space having been freed.

The explanation: inside WSL, freed space gets marked as such via a process called Trim — but that doesn’t automatically mean Windows recognizes those blocks as physically reclaimable. diskpart compact and WSL's internal trimming don't always play nicely together. Freshly pruned space seems especially prone to this, while old accumulated empty space - like what my first compaction caught - gets picked up reliably.

For anyone who wants to dig deeper: several sources mention Optimize-VHD -Mode Full from the PowerShell Hyper-V module as a more reliable alternative, with reported gains in the double-digit GB range. I haven't tested it myself, so I can't vouch for it - just flagging it for the curious. For most people, what's described here is more than enough.

The final tally

The raw numbers, no rounding:

  • VHDX before: 171 GB
  • VHDX after compact vdisk: 112 GB (−59 GB, pure air, zero data loss)
  • Build cache before: 48.38 GB, 13.89 GB reclaimable
  • Build cache after builder prune: 34.50 GB, 0 B reclaimable (−13.88 GB)
  • Second compact attempt after prune: no further change

A good third of that original 171 GB was either file bloat or actual removable junk. No broken configs, no mystery — just a system designed to never clean up after itself unless you explicitly make it.

The quick version for the impatient

If you want to run through this yourself, here’s the order that worked for me:

  1. Back up the VHDX file (shut down WSL completely first — budget an hour and a half at 171 GB)
  2. Run docker builder prune (and docker image prune, docker volume prune if needed) while Docker is still running
  3. Quit Docker Desktop, run wsl --shutdown
  4. Run diskpart compact vdisk - and don't abort it, even if nothing seems to be happening for 10–15 minutes
  5. Start Docker Desktop normally

This order — clean first, then compact — makes more sense than the reverse, even if, as my second attempt showed, a follow-up compaction doesn’t always do anything extra. Doesn’t hurt to try though.

Whether the effort is worth it depends on your situation. For me it was nearly 60 GB on an SSD that was already tight — no new hardware required. In a time when storage prices are going the wrong direction, that’s not a bad trade for an hour and a half of waiting and a little patience in front of a blinking cursor.

Disclaimer

This text was written by hand in the beginning, it then was developed and created — and may have been revised — partially with the help of tools such as Claude, Claude Code, ChatGPT or Gemini (among other GenAI tools), based on a current project. Code-Snippets are pure LLM-Code — so use it as always when dealing with AI generated content!

After all the original German version was translated to English by Claude


메타데이터
post_id
3b378ec4d63f
slug
docker-has-been-hoarding-your-disk-space-for-years-3b378ec4d63f
url
https://medium.com/rigel-computer-com/docker-has-been-hoarding-your-disk-space-for-years-3b378ec4d63f
canonical_url
https://medium.com/rigel-computer-com/docker-has-been-hoarding-your-disk-space-for-years-3b378ec4d63f
author_url
https://medium.com/@rigel-computer
status
ok
fetched_at
2026-06-24 04:09:36