Docker 磁盘满了,先运行 docker system df -v 查看资源占用,再检查容器日志和挂载目录。优先清理确认可重建的构建缓存、悬空镜像与废弃容器;数据卷需要单独确认归属和备份,不能因为显示“未使用”就删除。
自托管服务运行几个月后,镜像版本、构建缓存、日志和业务数据可能一起增长。
一次 prune 只能处理其中一部分,盲目扩大清理范围还可能删掉数据库。
本文以 Linux Docker Engine 和 Compose V2 为主要环境。 Docker CLI 查询命令通常也能在 Windows PowerShell 中执行;标为 Bash 的宿主机命令应在实际运行 Docker 的 Linux 主机执行。 文档核对日期为 2026 年 10 月 22 日,本文没有在你的服务器上执行清理或重建操作。
如果你从 Docker 部署 Syncthing 或 Joplin Server 自托管教程 延伸到这里,先找到那些服务实际使用的数据目录,再决定清理对象。
先确定满的是哪块盘、连接的是哪台主机
Docker CLI 可能连接本机、远端 SSH context,或 Docker Desktop 的 Linux 虚拟机。 在错误的 context 下查看空间,得到的数字可能和当前服务器完全无关。
|
|
重点核对服务端信息、当前 context 和 Docker 数据目录。
Linux 上默认数据目录经常是 /var/lib/docker,但 rootless、自定义配置和不同存储后端可能使用其他路径。
不要把这个默认路径直接当成待删除目录。
在 Linux 宿主机检查文件系统容量和 inode:
|
|
如果磁盘还有容量,但 inode 已经耗尽,大量小文件也会触发 no space left on device。
如果写入目标是绑定挂载的其他磁盘,则应检查那个挂载点,而不是只看系统盘。
Docker Desktop 还存在虚拟磁盘这一层。 容器内部释放的空间、虚拟磁盘的可用容量、宿主机磁盘文件实际占用,可能不会同步变化。 因此,Windows 的 C 盘没有立即变小,不能单独证明 Docker 清理失败。 本文不提供通用于所有 Desktop 后端的虚拟磁盘压缩命令。
用占用明细区分五类数据
先执行只读查询:
|
|
docker system df 展示 Docker 资源占用,-v 展开镜像、容器和本地卷的明细。
镜像之间可能共享层,不能把每个镜像显示的 SIZE 简单相加当成实际占用。
| 类型 | 常见内容 | 优先处理方式 |
|---|---|---|
| 镜像 | 当前版本、旧版本、构建中间产物 | 保留回滚版本,检查后清理悬空镜像 |
| 容器可写层 | 未持久化的上传文件、临时文件 | 确认数据能否丢弃或迁出 |
| 构建缓存 | Dockerfile 各步骤的可复用结果 | 按时间清理,接受后续构建变慢 |
| 数据卷与绑定挂载 | 数据库、配置、附件、模型 | 按应用管理,先备份再调整 |
| 容器日志 | 标准输出、标准错误 | 查明日志驱动,配置轮转 |
RECLAIMABLE 表示符合资源回收条件的占用估算,不能据此判定业务是否还需要这些资源。
比如旧镜像可能是唯一可用的回滚版本,未被引用的数据卷可能存着已经下线但仍需保留的数据库。
docker ps --size 中的可写层大小,也不等于挂载数据和日志的总大小。
如果这里显示很小,而宿主机磁盘仍在快速增长,就要沿着后面两条线检查。
清理前先画清容器与数据的对应关系
假设待检查容器名为 my-app,先替换成自己的实际名称:
|
|
在 Mounts 中重点看:
Type:区分volume和bind。Name:Docker 管理的数据卷名称。Source:宿主机来源路径。Destination:容器内的挂载位置。RW:容器能否写入。
例如,容器内 /data 映射到宿主机 /srv/my-app/data,那么该目录增长需要在宿主机和应用层排查。
删除旧镜像不会缩小这里的附件库。
如果数据库数据仍写在容器可写层里,先安排备份和持久化迁移。 此时删除容器可能直接丢失数据,不适合进入下面的容器清理步骤。
Compose 项目还应在正确的项目目录运行:
|
|
有自定义 -f、-p 或环境文件时,查询与后续操作要使用同一组参数。
改变项目名可能创建另一组卷,让应用看起来像“数据清空了”。
记录实际卷名、Compose 文件和镜像版本,备份文件放到有足够空间的独立位置。 数据库使用其自身支持的逻辑备份或一致性快照方式;运行中直接打包数据库目录可能得到无法恢复的备份。
镜像和构建缓存:从可重建的内容开始
先评估构建缓存
如果空间主要来自 Build Cache,清理缓存通常比触碰业务卷更合适。 代价是下次构建可能重新下载依赖、编译并消耗更多时间。
|
|
这会按时间条件清理符合条件的构建缓存,并保留交互确认。
168h 是七天,属于示例保留窗口,应根据构建频率调整。
它不是“预览”,确认后会实际删除缓存。
具体参数见 docker builder prune。
使用 Buildx 的多 builder 环境时,还要检查当前 builder:
|
|
docker buildx du 查询当前选中 builder 的缓存占用。
不要在一个 builder 上看到缓存大,却在另一个 builder 上反复执行清理。
多台远端构建机也需要分别核对,不能假定它们共享本机磁盘。
再判断悬空镜像能否删除
列出悬空镜像:
|
|
确认这些构建产物已经不需要后,可以执行:
|
|
默认清理悬空镜像。
加 -a 后范围扩大到没有容器引用的镜像,包括带有正常标签的旧版本。
这会影响离线恢复和版本回滚,不能把它当成默认加速参数。
完整规则见 docker image prune。
如果只想删除一个已经确认废弃的镜像,指定实际镜像 ID 更容易控制范围:
|
|
遇到引用冲突时,先检查引用它的容器,重新判断是否仍需保留。 不要立即添加强制参数绕过这个提示。
废弃容器按名称逐个处理
停止状态不代表容器里的文件没有价值。 先查看容器的挂载和可写层,再决定是否删除:
|
|
docker diff 可用于查看容器文件系统变更,不是备份,也不能代替检查挂载目录。
确认这是可丢弃的测试容器后,才删除指定对象:
|
|
此处没有使用 -f 或 -v。
删除容器仍会丢弃其可写层和容器日志;重要文件必须提前导出。
删除规则可查 docker container rm。
日志持续增长:清缓存之后还要处理根因
如果 docker system df 中可回收空间很少,继续查看日志驱动和路径。
Docker 默认的 json-file 日志驱动没有默认大小限制,高频错误输出可能持续占用磁盘。
|
|
默认驱动和某个容器的实际驱动可能不同,以容器的 LogConfig 为准。
LogPath 也不一定始终提供可直接查看的文件路径,取决于日志驱动和运行环境。
配置行为见 Docker 日志驱动文档。
在 Linux 上,可对实际返回的路径执行只读大小查询。 例如把下面路径替换为刚查询到的日志文件:
|
|
不要直接删除或截断 Docker 管理的日志文件。 官方说明这些文件由 Docker daemon 独占管理,外部修改可能干扰日志系统。 如果日志是不断重复的数据库连接失败或权限错误,先解决应用问题,单纯轮转仍会产生大量无用日志。
为 Compose 服务设置日志轮转
把下面的 logging 配置合并到现有服务中,保留原来的镜像、端口、环境变量和数据挂载:
|
|
这只是配置片段,不是可独立启动的完整 Compose 文件。
app 要替换成实际服务名。
max-size 控制单个日志文件的轮转阈值,max-file 控制保留文件数量;具体规则见 json-file 文档。
修改后先检查语法,在业务允许短暂中断、数据已持久化并备份的前提下重建目标服务:
|
|
重建会替换容器,其可写层内容不会自动保留。 如果服务依赖匿名卷,应先明确后续如何复用或迁移这些卷,再执行重建。 随后找到新容器的实际名称并检查:
|
|
只修改配置后运行 docker compose restart 不会更新容器创建时确定的日志选项。
如果检查仍显示旧配置,核对服务名、Compose 文件、项目名和实际容器 ID。
轮转会限制本地历史日志,需长期审计的业务应另行采集与保留。 应用自己写入挂载目录的日志,也需要应用配置或合适的轮转机制;Docker 的标准输出轮转不会管理那些文件。
数据卷:未使用和可删除是两回事
列出没有容器引用的卷,可以帮助找到待核查对象:
|
|
卷没有关联容器,可能只是因为执行过 docker compose down。
容器删除后,卷里的数据库文件仍可能是下一次启动所需的全部业务数据。
卷的持久化机制见 Docker Volumes 文档。
实际处置前,应能回答四个问题:
- 这个卷属于哪个应用和哪个环境?
- 应用是否已经永久下线,还是准备稍后重建?
- 是否存在独立备份,且验证过恢复方法?
- 备份存放位置是否会被这次清理一并删除?
只有确认不再需要的指定卷,才考虑用 docker volume rm 实际卷名 删除。
本文不把批量数据卷清理作为日常维护步骤。
数据卷增长来自数据库记录、附件或模型时,应先使用应用支持的保留策略、归档或迁移流程。
prune 与 compose down 的边界
不同命令的删除范围不能混用:
| 命令或选项 | 需要理解的范围 |
|---|---|
docker image prune |
默认针对悬空镜像 |
docker image prune -a |
扩展到所有没有容器引用的镜像 |
docker system prune |
涉及停止容器、未使用网络、悬空镜像和未使用构建缓存 |
docker system prune --volumes |
额外涉及未使用匿名卷,不能理解为备份清理 |
docker volume prune |
当前默认清理未使用匿名本地卷;--all 扩大到未使用命名卷 |
docker compose down |
默认移除项目容器和网络,不主动删除数据卷 |
docker compose down -v |
额外删除声明的命名卷和附属匿名卷;external 卷除外 |
参数行为以安装版本的 --help 和当前官方文档为准。
参见 system prune、volume prune 和 compose down。
批量清理不是一次可撤销的操作。
缓存可以重新生成,镜像可能重新拉取,已删除的数据卷则需要有效备份才能恢复。
另外,Compose 默认不删除匿名卷,不代表下次 up 一定能自动挂回原来的匿名卷。
长期业务应使用明确的数据路径或命名卷,并保存对应配置。
清理后用空间变化和业务读写共同验收
每处理一类资源就重新查看一次,便于知道究竟释放了哪里:
|
|
Linux 宿主机再检查:
|
|
不能只凭容器显示 Up 就宣布恢复。
至少打开一次服务、读取一条已有记录、写入一条可删除的测试记录,再确认数据库或同步目录确实使用原来的数据。
涉及日志重建的服务,还要观察一段时间的磁盘增长,确认轮转配置和应用错误都已处理。
如果释放量明显少于预期,按现象继续定位:
| 现象 | 下一步检查 |
|---|---|
| 镜像列表很大,实际只释放少量空间 | 镜像共享层、仍被容器引用的层 |
| Build Cache 没变化 | 当前 context 和 builder 是否一致 |
| Docker 资源很小,磁盘仍满 | 绑定挂载目录、日志、其他宿主机文件 |
| Linux 仍报空间不足 | 实际目标文件系统、inode、配额和存储后端 |
| Desktop 内可用空间增加,宿主机占用不变 | 对应平台的虚拟磁盘回收机制 |
| 容器重建后出现初始化页面 | 项目名、卷名、绑定路径或匿名卷关联发生变化 |
最后一种情况应立即停止继续写入,核对旧卷是否还在、配置是否指向新目录。 不要接着运行卷清理,否则可能把仍可找回的旧数据真正删除。
若清理后服务异常,先还原 Compose 配置,检查持久化挂载,再使用保留的镜像版本重建。 如果卷已经删除,重新拉镜像不会恢复业务数据,需要按事先验证过的备份流程恢复。
后续维护怎样安排
维护记录至少包括 Docker context、资源占用、实际数据目录、日志驱动和备份位置。 构建频繁的开发机可以定期评估缓存;长期运行数据库的服务器,应把容量告警、数据库备份和恢复演练放在更高优先级。
不要把带强制参数、镜像全量清理和卷清理的命令直接放进定时任务。 先运行一段时间的只读统计,确认哪些资源稳定增长,再选择对应的保留策略。
需要把数据迁到另一块盘时,可参考 rsync 增量同步与校验。 对数据库目录,仍需先停止相关写入或使用应用支持的一致性备份;文件复制成功不等于数据库备份可恢复。