在 Windows 上使用 Docker Desktop 跑 CentOS 容器的开发者,经常会遇到一个奇怪的现象:容器明明只写了几十 GB 的日志或数据,C 盘却直接飘红告急,甚至整个系统卡到鼠标都动不了。很多人第一反应是怀疑 Windows 自己出了问题,反复清理浏览器缓存、卸载软件,结果空间一点没回来。其实罪魁祸首往往是 Docker 在 WSL2 中的虚拟磁盘文件被撑大了。本文就来把这件事的来龙去脉讲清楚,并给出完整的排查和解决方案。

一、容器磁盘为什么会撑爆 Windows 宿主机
先理解存储结构。Docker Desktop 在 Windows 上默认基于 WSL2 运行,所有容器、镜像、数据卷都存放在一个 ext4 格式的虚拟磁盘文件里,典型路径是 C:\Users\你的用户名\AppData\Local\Docker\wsl\data\ext4.vhdx。如果你的机器装的是旧版 Docker Desktop 或使用了其他 WSL 发行版,也可能在 C:\Users\你的用户名\AppData\Local\Packages\ 下找到类似的 vhdx 文件。
关键点在于:WSL2 的虚拟磁盘是“只增不减”的动态扩容机制。CentOS 容器里往 /var/log 写入大量日志,或者应用不断生成临时文件时,vhdx 文件会随之膨胀。但即使你在容器里把这些文件删掉了,vhdx 也不会自动缩小。这就像一个只能吹大不能放气的气球,时间一长 C 盘自然被占满。
另一个常见膨胀源是容器日志驱动。Docker 默认使用 json-file 日志驱动且不限制大小,一个高频打日志的 CentOS 容器跑上几周,单个日志文件涨到几十 GB 很常见。这些日志全部落在虚拟磁盘里,最终都算在 Windows 的 C 盘头上。
二、如何定位是哪个容器在吃磁盘
排查要从两头看。先在 Windows 侧确认 vhdx 文件的实际大小,打开文件资源管理器进入 C:\Users\你的用户名\AppData\Local\Docker\wsl\data\ 目录,看 ext4.vhdx 占了多少空间。如果它有几十 GB 甚至上百 GB,基本可以确定问题出在 Docker 内部。
接下来进 Docker 内部找元凶,按容器维度查看磁盘占用:
# 查看所有容器的磁盘写入情况(SizeRw 是可写层大小) docker ps -a --size # 查看 docker 整体磁盘占用分布 docker system df -v
如果发现某个 CentOS 容器的可写层异常大,多半是应用直接往容器可写层写数据了。再检查日志文件大小:
# 进入容器查看日志和临时目录占用 docker exec -it centos-container /bin/bash du -sh /var/log /tmp /var/lib # 查看宿主机侧的容器日志文件大小(在 WSL 内执行) du -sh /var/lib/docker/containers/*/*-json.log
还要注意数据卷。有些容器把数据写进匿名卷,docker rm 删掉容器后卷还残留着。用 docker volume ls 配合 docker system prune --volumes 可以把这类孤儿卷清掉,但在执行前务必确认里面没有需要保留的数据。
三、限制容器日志和存储增长
找到元凶后,治本的办法是从源头限制增长。日志方面,在 Docker Desktop 的 Settings 中打开 Docker Engine 配置,或直接编辑 daemon.json,加上日志轮转限制:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "3"
}
}
这样每个容器的日志最多占 150 MB 左右,超过后自动轮转删除旧日志。注意这个配置只对新建容器生效,已有容器需要重建。也可以在 docker run 时通过 --log-opt max-size=50m 单独指定。
除了日志,还要管住容器可写层。正确的做法是把频繁写入的目录挂载为数据卷,便于统一管理和清理:
docker run -d \ --name centos-app \ -v docker-app-logs:/var/log \ -v docker-app-tmp:/tmp \ centos:7
对于只是用来构建镜像的场景,构建缓存也是磁盘大户。定期执行 docker builder prune 清理无用的构建层,执行 docker image prune -a 清理不再使用的镜像,能回收大量空间。如果希望更激进一些,可以直接用 docker system prune -a --volumes 一把梭,但删掉的镜像需要重新拉取,生产环境慎用。
四、压缩 ext4.vhdx 把空间还给 Windows
前面说过,即使容器里删了文件,vhdx 也不会自动缩小。清理完容器内部之后,还需要手动压缩虚拟磁盘,才能真正把空间还给 Windows。操作前先在系统托盘退出 Docker Desktop,确保没有容器在跑。
第一步查看 WSL 发行版名称:
wsl --list -v
然后执行压缩。较新版本的 WSL 支持直接压缩:
# 关闭所有 WSL 实例 wsl --shutdown # 压缩指定发行版的虚拟磁盘 wsl --manage docker-desktop-data --set-sparse true
如果系统版本较旧不支持上述命令,可以用 Windows 自带的 diskpart 工具。以管理员身份打开 PowerShell,依次执行:
diskpart # 在 diskpart 交互界面中执行: select vdisk file="C:\Users\你的用户名\AppData\Local\Docker\wsl\data\ext4.vhdx" compact vdisk exit
压缩过程可能持续几分钟,取决于 vhdx 的大小和碎片程度。完成后重新启动 Docker Desktop,再去看 ext4.vhdx 的体积,通常会有明显缩小。建议把这套“容器内清理加 diskpart 压缩”的流程纳入定期维护,比如每个月执行一次,避免磁盘再次被悄悄占满。
五、日常预防的几点建议
总结几个实用习惯:第一,全局配置日志轮转,这是收益最大的一步;第二,凡是往磁盘写数据的容器,一律挂载具名卷,不要让数据散落在可写层;第三,把大体积数据目录通过 -v 挂载到 Windows 侧目录(如 D:\docker-data),既便于备份也避免全挤在 C 盘;第四,定期执行 docker system df 做体检,发现异常增长及时处理。做到这几点,CentOS 容器再怎么折腾,也很难再把 Windows 宿主机拖下水了。