一、问题
在Windows系统中安装Docker Desktop时,是无法选择安装的位置的,程序默认将Docker安装到了C盘。在使用Docker的过程中,我们会下载镜像文件,而一个镜像文件动辄10几G,都会被放到C盘里存储Docker数据的磁盘映像文件(.vhdx)中。由于vhdx文件的特性,即使在Docker中删除掉不用的镜像文件,vhdx文件也不会释放存储空间,这样电脑的C盘很快就会被占满。
原来是因为:👉 Docker Desktop的虚拟磁盘(如ext4.vhdx、docker_data.vhdx)在Windows系统中不会自动缩减空间占用。即使实际使用空间远低于最大值,系统仍会保留虚拟磁盘曾经达到的最大容量。

其实之前直接也有过类似情况,之前解决方法是直接删除docker重装,但是没有过多久又出现了这个问题,于是我这次打算下定决心要彻底从根源上解决这个问题,于是我开始在网上找了很多种解决方案。
二、背景
Docker占用的磁盘空间主要来自以下几个方面:
- 镜像(Image): 在日常不断地拉取和构建镜像的过程中堆积的镜像文件
- 容器(Container): 停止或未使用的容器
- 卷(Volume): 用于持久化数据的卷
- 构建缓存(Build Cache): 在构建镜像时产生的缓存文件
其中,卷中有可能涉及数据库以及其他持久化存储的数据,需要谨慎清理;此外如果有频繁构建镜像的需求,构建缓存也应考虑保留。所以我们主要是针对镜像和容器进行清理。
Windows系统下,Docker通常使用WSL2。WSL2本质上是一个虚拟机,而Docker的所有数据都存储在WSL2的虚拟磁盘中(以.vhdx
文件的形式),随着时间的推移,这个虚拟磁盘会自动扩容,但并不会自动收缩,因此需要手动进行清理和压缩。
PS: 我的系统环境为Windows 11 家庭版 23H2,Docker版本为Docker Desktop 4.45.0 (203075)。Windows家庭版不支持Hyper-V,所以之后压缩虚拟磁盘的步骤需要使用diskpart
命令。
三、解决方案
方案一:迁移映像文件到其他盘
这种方案只适用于C盘以外的其他盘有剩余空间的人,小宁其他盘的空间也比较紧张,所以并没有使用这种解决方案,大家可以参考,尝试一下把WSL迁移到其他磁盘,所以也有了后续的方案二,以下是小编找到的两篇博客,大家可以参考。
docker占用C盘过大的问题:WSL(Windows)一键迁移Docker磁盘_docker c盘-CSDN博客
windows11 安装 docker desktop (包含数据迁移到D盘存储)_docker desktop安装到d盘-CSDN博客
方案二:压缩vhdx文件
后续小宁又在网上找了很多种解决方案,于是找到了一个网上呼声很高的解决办法,这里先把具体的网址给大家:
适用于 Linux 的 Windows 子系统 - Docker 桌面 WSL ext4.vhdx 太大 - Stack Overflow
如何管理 WSL 磁盘空间 | Microsoft Learn
容器化运维:Docker Desktop 占用磁盘空间过大?教你轻松解决!-阿里云开发者社区
下面教一下打击具体的操作步骤:
1、管理员身份打开cmd

2、逐步执行一下指令
解决办法:
①wsl --shutdown
关闭所有WSL,cmd 或 powershell工具都可以
bash
wsl --shutdown
②diskpart
打开工具,会自动新开一个cmd窗口
bash
diskpart
③select vdisk file="
<you_path>\docker\disk\docker_data.vhdx"
自己环境下Docker Desktop
的虚拟磁盘的路径。
bash
select vdisk file="C:\Users\....\AppData\Local\Docker\wsl\disk\docker_data.vhdx"
④compact vdisk
执行压缩,等待进度跑完
bash
compact vdisk
⑤exit 退出diskpart窗口
bash
exit
最后再启动wsl服务即可,可能还需重启。

可能大家以为这就完了,我也是这么觉得的,但是在很多人使用的方案在我这里缺起不到什么作用,仅仅只给我腾出来了600多MB,让我实在恼火不以,气的我差点又要重装docker,但是我还忍住了,所以后续又有了我的方案三。

方案三:通过指令删除未使用的资源
1、确认当前Docker的磁盘使用情况
docker system df
2. 清理未使用的资源
docker container prune && docker image prune -a
3、更完整的常用清理命令及其作用范围如下:
命令 / 参数 | 删除对象范围 | 说明 / 风险 |
---|---|---|
docker image prune |
悬空镜像 (<none> ) |
仅删 dangling 层,安全。 |
docker image prune -a |
未被任何容器引用的镜像 | 需重拉/重建,运行中容器依赖的不会删。 |
docker container prune |
已停止容器 | 不影响运行中容器。 |
docker volume prune |
未使用卷 | 会删数据,谨慎使用。 |
docker network prune |
未使用自定义网络 | 不含默认网络,一般安全。 |
docker system prune |
停止容器、未用网络、悬空镜像、可回收缓存 | 常用清理,不含卷。 |
docker system prune -a |
停止容器、未用网络、未引用镜像、缓存 | 更彻底,不含卷。 |
docker system prune --volumes |
同上 + 未用卷 | 最激进,卷数据会丢失。 |
docker builder prune |
可回收构建缓存 | 可能影响 build 速度。 |
docker builder prune -a |
所有构建缓存 | 最彻底,后续 build 变慢。 |
-f / --force |
跳过确认提示 | 脚本常用,交互下慎用。 |
结果最后效果还是微乎其微,刚刚释放出来的内存又被占用了回去了,无奈只有采用暴力手段了。
方案四:暴力清空所有数据(慎用)
这种方案虽然肯定能够解决你的内存占用过高的问题,但是也会带来一个问题,就是配置好的docker环境和之前拉取的相关镜像都要重新配置和下载,小宁也是实在无奈才出此下策。



这样一顿处理之后虽然说内存回来了,但是后续可能还是会出现这样的问题,并没有从根源上解决这个问题。

大家有什么其他的更好的解决方案,可以一起交流,帮我彻底解决这个问题。