摘要:Docker 在 macOS 上运行几个月后,磁盘占用轻轻松松超过 30GB——不是因为镜像太多,而是因为虚拟机磁盘镜像只增不减、构建缓存从不自动清理、退出容器后的卷成了孤儿。本文从三层诊断入手——Docker 自身的 system df 数据、macOS 文件系统层的 SpacePeek 空间分析、以及 Docker Desktop 的磁盘镜像占用——给出分级清理策略(安全 / 标准 / 激进),每一步标注可回收空间量和风险等级。文末提供按月执行的自动化脚本。

本文信息:基于 Docker Desktop for Mac (Apple Silicon)、macOS 15.0 Sequoia、Docker Engine 26+ 实测。清理命令适用于 Docker 26+ 版本,低版本需注意命令兼容性。


一、问题背景

Docker 的磁盘占用不是 bug,是设计

Docker 在 macOS 上的运行机制和 Linux 完全不同。在 Linux 上,Docker 直接跑在宿主机内核上,镜像和容器数据存在本机文件系统里。但在 macOS 上,Docker 跑在一个轻量 Linux 虚拟机里——这个虚拟机的磁盘镜像(Docker.raw)是一个只增不减的稀疏文件。

关键问题就出在"只增不减"这四个字。

你拉了一个 2GB 的镜像,用完了删掉——虚拟机镜像文件不会缩小。你跑了 100 次 docker build,每次都产生构建缓存——虚拟机镜像文件只增不减。你创建了 10 个数据卷,项目结束后删了容器但忘了删卷——虚拟机镜像文件继续增大。

结果就是:用了三个月 Docker 之后,你去 ~/Library/Containers/com.docker.docker/ 一看——Docker.raw 已经 45GB 了。


二、三层诊断:找到 Docker 到底吃了你多少空间

第 1 层:Docker 自己的数据统计

docker system df

输出解读

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          45        12        8.7GB     5.2GB (59%)
Containers      18        6         1.1GB     620MB (55%)
Local Volumes   5         3         120MB     50MB (40%)
Build Cache     0         0         0B        0B

怎么看

  • ImagesRECLAIMABLE 数字——这些是可以安全回收的未使用镜像
  • ContainersRECLAIMABLE——已退出但未删除的容器
  • Local VolumesRECLAIMABLE——未被任何容器挂载的卷(孤儿卷)
  • Build Cache——docker build 的中间层缓存

进阶命令

docker system df -v    # 详细列出每个镜像/容器/卷的大小

第 2 层:macOS 文件系统层的实际占用

# 查看 Docker 虚拟机磁盘镜像的实际大小
ls -lh ~/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw

典型输出45GB。但 Docker Desktop 设置里显示"已使用 28GB"——为什么差 17GB?因为 Docker.raw 是稀疏文件,它从 0 开始只增不减,即使你删除了镜像,这个文件也不会自动缩小。这是 macOS 版 Docker 最核心的空间问题。

如果你装了 SpacePeek:在 Finder 里进入 ~/Library/Containers/com.docker.docker/ → 按空格 → 饼图会告诉你 Data/vms 占了 95% 以上。不需要手动逐层 ls -lh,一眼定位。
在这里插入图片描述

第 3 层:Docker Desktop 的资源面板

Docker Desktop → 右上角齿轮 Settings → Resources → 可以看到:

  • Disk image size:当前磁盘镜像的实际占用(包含稀疏文件中的"空洞")
  • Disk image max size:镜像文件允许的最大体积(默认通常设为 64GB 或 128GB)

如果 Disk image size 接近 max size,你需要进行"激进清理"(见下文)。


三、分级清理策略

⚠️ 清理原则:安全优先。先从低风险操作开始,释放量不够再逐步升级。


🟢 Level 1:安全清理(零风险,释放 5-15GB)

这些命令只删除未被任何运行中容器使用的资源。不会影响你正在开发的项目。

# 1. 清理悬空镜像(<none>:<none>)
docker image prune -f

# 2. 清理已停止的容器
docker container prune -f

# 3. 清理未被使用的卷
docker volume prune -f

# 4. 清理构建缓存
docker builder prune -f

每次预期释放:5-15GB(取决于你上次清理是什么时候)。


🟡 Level 2:标准清理(低风险,释放 10-25GB)

这些命令会删除所有未被运行中容器使用的镜像、构建缓存和网络。不会影响正在运行的容器,但会删除已停止容器的镜像和缓存。

# 一条命令搞定 Level 1 + Level 2 的全部清理
docker system prune -a --volumes -f

参数解释

参数作用
-a删除所有未被使用的镜像(不只是悬空的)
--volumes同时删除未被使用的卷
-f跳过确认提示

⚠️ 注意-a 会删除所有未运行容器的镜像。如果你有一个停止的容器需要保留其镜像,先用 docker images 确认。

每次预期释放:10-25GB。


🔴 Level 3:激进清理(中风险,释放 20-40GB)

场景:Level 2 清理之后,Docker.raw 文件仍然很大——因为你已经删除了所有可清理的数据,但磁盘镜像文件本身没有缩小。

原因:Docker Desktop 的虚拟机磁盘镜像是稀疏文件,内部数据删除后,占用的空间不会还给 macOS。你需要手动压缩这个文件。

操作步骤

1. Docker Desktop → Troubleshoot → Reset to factory defaults
   ⚠️ 这会删除所有容器、镜像、卷、构建缓存——相当于重装 Docker

2. 替代方案(保留部分数据):
   Docker Desktop → Settings → Resources → Advanced →
   将"Disk image size"调到一个较小的值(如 32GB)→ Apply & Restart
   Docker 会自动压缩镜像文件到设定值以下

注意:Level 3 只在你确认"所有重要的 Docker 数据已经不需要了"时执行。如果你有需要保留的镜像,先用 docker save 导出。


四、预防:写一个按月执行的脚本

比清理更重要的是——不要回到"每季度突然发现 Docker 占了 50GB"的循环。

#!/bin/bash
# ~/scripts/docker-monthly-cleanup.sh
# 每月执行一次,放在 crontab 里

echo "===== $(date) =====" >> ~/docker-cleanup.log

echo "清理前使用情况:" >> ~/docker-cleanup.log
docker system df >> ~/docker-cleanup.log

echo "→ 清理悬空镜像..." >> ~/docker-cleanup.log
docker image prune -f >> ~/docker-cleanup.log 2>&1

echo "→ 清理退出容器..." >> ~/docker-cleanup.log
docker container prune -f >> ~/docker-cleanup.log 2>&1

echo "→ 清理构建缓存..." >> ~/docker-cleanup.log
docker builder prune -f >> ~/docker-cleanup.log 2>&1

echo "清理后使用情况:" >> ~/docker-cleanup.log
docker system df >> ~/docker-cleanup.log
echo "---" >> ~/docker-cleanup.log

设置每月自动执行

chmod +x ~/scripts/docker-monthly-cleanup.sh
crontab -e
# 加入:0 9 1 * * ~/scripts/docker-monthly-cleanup.sh
# 每月 1 号上午 9 点执行

五、关于 macOS 版 Docker 的一个认知纠正

有人会说"Docker 在 macOS 上就是吃资源"——这不完全对。

Docker Desktop 在 macOS 上需要虚拟机,这是物理上无法绕过的事实。但"磁盘镜像只增不减"的原因不是 Docker 做得差,而是 macOS 的 Hypervisor 框架对稀疏文件的管理方式和 Linux 的 OverlayFS 不同。

你能做的是:主动管理。每月 run 一次 Level 1-2 清理 + 看一眼 SpacePeek 确认 Docker.raw 没膨胀到离谱。养成这个习惯之后,Docker 的磁盘占用不再是问题。


六、总结

三点核心

  1. Docker on macOS 的磁盘膨胀分两层:Docker 内部的数据层(镜像/容器/卷/缓存,用 docker system df 诊断)和 macOS 文件系统层(Docker.raw 虚拟机磁盘镜像,用 ls -lh 或 SpacePeek 诊断)。两层都要清理,缺一不可。

  2. 清理有三级,按需升级:Level 1(悬空资源,5-15GB,零风险)→ Level 2(全部未使用资源,10-25GB,低风险)→ Level 3(压缩磁盘镜像,20-40GB,中风险)。绝大多数情况 Level 2 就够了。

  3. 预防比清理更重要。 一个月执行一次 Level 1 清理,比半年执行一次 Level 3 重置更安全、更省时间。配合 SpacePeek 的 Finder 侧随手按空格,你可以在日常浏览文件时顺便知道 Docker.raw 有没有偷偷膨胀。

涉及的工具

工具文中角色获取
docker system dfDocker 内部数据诊断Docker 自带
docker system pruneDocker 内部数据清理Docker 自带
SpacePeekmacOS 文件系统层诊断App Store 免费
crontab自动执行清理脚本macOS 自带

测试环境:Docker Desktop for Mac (Apple Silicon) / Docker Engine 26 / macOS 15.0 Sequoia / 2026 年 7 月


你的 Docker 最长多久没清理过?评论区晒一下 docker system df 的 RECLAIMABLE 数字——让我看看谁的最离谱。

更多推荐