# Docker 和 WSL 占了很多空间，先看清数据在哪一层

在 Docker Desktop 里一顿清理，提示已经释放了 20 GB 空间，切回 Windows 资源管理器一看，C 盘可用空间居然连 1 MB 都没有涨。遇到这种怪事，先别以为软件在骗你。Docker 容器、镜像和数据卷是存放在 WSL2 的 Linux 虚拟磁盘文件（`ext4.vhdx`）里的。Docker 内部删掉文件，只是在虚拟磁盘内部把这块空间标为了“空闲可重用”，但 Windows 宿主机视角下的那个虚拟磁盘文件，默认是**不会自动瘦身缩容**的。

## 先搞清楚当前 Docker 在连接哪套环境

在 PowerShell 里运行下面几条只读命令，先看一眼全局状态：

```powershell
docker context show
docker system df -v
docker ps -a
docker volume ls
wsl --list --verbose
```

[Docker 上下文文档](https://docs.docker.com/engine/manage-resources/contexts/)指出，如果你设置了 `DOCKER_HOST` 连到了远程服务器，那本地查出来的全是服务器上的容器，跟本机 C 盘没有半毛钱关系。[WSL 后端说明](https://docs.docker.com/desktop/features/wsl/)则解释了 Docker 在 Windows 下是通过专用的 WSL2 发行版（如 `docker-desktop` 和 `docker-desktop-data`）来管理底层数据的。

## 镜像大小不是简单相加：理解共享分层

[Docker 官方空间统计](https://docs.docker.com/reference/cli/docker/system/df/)把镜像拆成了共享层与可写层。比如你的五个镜像都是基于同一个 `ubuntu:22.04` 基础镜像构建的，那底层那 100 多兆的基础层只会落盘存储一份。删掉其中一个镜像，并不会释放这 100 多兆共享空间。

| Docker 对象 | 里面装的到底是啥 | 清理前要注意 |
| --- | --- | --- |
| 镜像（Images） | 运行环境与预装程序分层 | 是否能随时从 Docker Hub 或私有源重新 pull 下来 |
| 容器（Containers） | 跑起来的应用实例与可写层 | 已经停止的容器里，有没有没导出的测试数据 |
| 构建缓存（Build Cache） | `docker build` 过程中复用的中间层 | 下次重新编译时是否愿意多等几分钟重新拉包 |
| 数据卷（Volumes） | 本地持久化挂载的数据（如 MySQL 库） | **极高风险**：没挂载的卷很可能是暂停了的数据库 |

看到没有容器使用的“无主数据卷”（Dangling Volumes），千万别盲目一键全清。那往往是昨晚刚停掉的开发数据库或本地测试数据。

## 想要清空间，最安全的是清构建缓存

如果只是想给日常开发回血几个 G，最稳妥、零风险的是清构建缓存（BuildKit Cache）：

```powershell
docker builder prune
```

[Docker 官方清理指南](https://docs.docker.com/reference/cli/docker/builder/prune/)明确说明，这条命令只会清理掉之前编译镜像时缓存的中间件，绝不会动你正在跑的容器和数据卷。如果敲重型命令 `docker system prune -a --volumes`，不仅会把所有未启动的容器干掉，还会把所有未挂载的数据库卷彻底格式化。

<figure class="blog-diagram">
  <picture>
    <source media="(max-width: 900px)" srcset="/img/blog/windows-docker-wsl-disk-space-windows-zh-mobile.webp" type="image/webp" width="768" height="1500">
    <img src="/img/blog/windows-docker-wsl-disk-space-windows-zh.webp" width="1360" height="454" loading="lazy" alt="Docker 内容的保留需求不同">
  </picture>
  <figcaption>暂时没引用的数据卷依然可能装着珍贵的测试库，共享层也会让实际释放的体积打折。</figcaption>
</figure>

## 为什么删了镜像，C 盘的 vhdx 文件依然不缩小

这是 WSL2 和虚拟磁盘的底层物理特性：**虚拟硬盘只会自动膨胀，不会自动回缩**。[微软 WSL 磁盘说明](https://learn.microsoft.com/en-us/windows/wsl/disk-space)详细解释了这个机制。

想要把物理空间真正吐还给 Windows C 盘，需要做一次“磁盘压缩（Compact）”：
1. 退出 Docker Desktop，在 PowerShell 里运行 `wsl --shutdown` 彻底关闭所有 Linux 子系统；
2. 找到对应的虚拟硬盘文件（通常在 `%LOCALAPPDATA%\Docker\wsl\data\ext4.vhdx`）；
3. 用 Windows 自带的 `diskpart` 工具，选择该 vhdx 文件并执行 `compact vdisk` 压缩。

千万别直接去资源管理器里把这个 `ext4.vhdx` 删了，那相当于把你的整个虚拟环境连根拔起。日常包管理器的缓存排查可以看[开发环境缓存指南](/zh/windows/blog/windows-developer-caches)。


Canonical: https://mole.fit/zh/windows/blog/docker-wsl-disk-space-windows
