使用 Docker 部署网站或自建服务后,服务器磁盘可能越来越满。更新应用留下的旧镜像、反复构建产生的缓存、已经停止的测试容器,都可能继续占用空间。
但 Docker 占用大,也可能是数据库、上传文件和日志正在增长。清理前需要先确定空间用在哪里,再选择对应的处理方式。
本文适用于已安装 Docker Engine 的 Linux 服务器。请在 Docker 实际运行的服务器上操作,使用 root 或具备相应权限的账号。

一、先确认哪个文件系统空间不足
查看服务器磁盘容量和使用率:
df -hT
重点关注 Use% 和 Mounted on,确定接近满载的是系统盘,还是保存 Docker 数据的数据盘。
如果还有剩余容量,却仍然提示 No space left on device,再检查 inode:
df -i
IUse% 接近 100%,可能意味着大量小文件耗尽了 inode,需要定位这些文件所在目录。
随后查看 Docker 的空间统计:
docker system df
常见分类如下:
| 分类 | 主要内容 | 排查方向 |
|---|---|---|
| Images | 本地镜像及其镜像层 | 是否保留了大量旧版本 |
| Containers | 容器可写层 | 是否有废弃容器或大量临时文件 |
| Local Volumes | Docker 数据卷 | 是否为数据库、上传文件等业务数据 |
| Build Cache | 镜像构建缓存 | 是否经常在服务器上构建镜像 |
RECLAIMABLE 表示 Docker 判断可以回收的空间,不代表这些内容对业务没有价值。
例如,一个暂时没有容器引用的数据卷,仍然可能保存着需要恢复的数据库。
二、查看具体镜像和容器的占用
查看详细统计:
docker system df -v
镜像部分需要注意三个字段:
SIZE:镜像总大小。SHARED SIZE:与其他镜像共享的空间。UNIQUE SIZE:仅由该镜像使用的空间。
多个镜像可能共享相同的底层数据,因此不能把每个镜像的 SIZE 直接相加,作为实际占用。
接着查看包括已停止容器在内的可写层大小:
docker ps -a --size \
--format 'table {{.Names}}\t{{.Status}}\t{{.Size}}'
这里的 SIZE 主要反映容器可写层,括号里的 virtual 包含镜像数据。
该统计不包含容器挂载的数据卷、宿主机目录,以及 Docker 日志驱动保存的日志。 因此,容器显示占用很小,也可能对应一个很大的数据库目录。
这些统计可能涉及较多文件扫描,容器和文件数量较多时,建议在业务低峰执行。
三、分别清理无用镜像与构建缓存
1. 清理悬空镜像
先查看悬空镜像:
docker image ls --filter dangling=true
悬空镜像通常没有标签,也没有容器引用。确认不需要保留后,执行:
docker image prune
命令会提示确认,输入 y 后开始清理。
如果考虑使用 docker image prune -a,需要知道它的范围更大:所有没有被任何现存容器引用的镜像,都可能被删除,包括带标签的镜像。
这可能包含为版本回退预留的镜像。仅保存在本机、没有推送到仓库的自建镜像,也应先确认能否重新构建。
2. 清理构建缓存
如果 Build Cache 占用明显,可以执行:
docker builder prune
根据提示确认后,Docker 会清理符合条件的构建缓存。默认不加 -a 时,清理范围为悬空构建缓存。
构建缓存用于加速后续构建。删除后,部分步骤需要重新执行,可能重新下载依赖,但该命令不用于删除运行中的容器或业务数据卷。
使用多个独立 Buildx 构建器时,各构建器的缓存需要分别检查,不能把一次清理理解为清空所有构建缓存。
四、逐个删除确认废弃的停止容器
容器停止后,可写层仍然占用磁盘。先列出已经退出的容器:
docker ps -a --filter status=exited \
--format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
不要仅凭 Exited 就判断它可以删除。它也可能是暂时停机的业务容器,或需要保留现场的故障容器。
假设确认要检查的容器叫 old-test,先替换下面的名称:
old_container='old-test'
docker inspect --format '{{.State.Status}}' "$old_container"
docker inspect \
--format '{{range .Mounts}}{{println .Type .Source "->" .Destination}}{{end}}' \
"$old_container"
第二条检查命令会列出挂载类型、宿主机来源及容器内路径。
确认容器确实废弃、可写层中的重要文件已经备份,并且不再需要保留其配置和日志后,执行:
docker rm "$old_container"
这条命令会直接删除指定容器及其可写层。 示例没有使用 -f 强制删除运行中的容器,也没有使用 -v 删除关联匿名卷。
挂载目录或数据卷能够保留,并不意味着容器内部所有文件都能保留。没有写入持久化挂载位置的数据,会随可写层一起消失。
五、数据卷和挂载目录要单独判断
如果占用主要来自 Local Volumes,或者容器可写层很小、磁盘却持续增长,就需要查看应用的数据挂载。
以 myapp 为例,替换为实际容器名称:
container_name='myapp'
docker inspect \
--format '{{range .Mounts}}{{println .Type .Source "->" .Destination}}{{end}}' \
"$container_name"
常见类型有:
| 类型 | 含义 | 处理方式 |
|---|---|---|
bind | 直接挂载宿主机文件或目录 | 检查对应 Source 路径 |
volume | 使用 Docker 管理的数据卷 | 结合卷名、应用配置和备份情况判断 |
假设确认某个 bind 挂载来源为 /home/myapp/data,可以查看该目录的占用:
du -sh -- /home/myapp/data
进一步查看一级子目录:
du -xhd1 -- /home/myapp/data | sort -h
这里的路径只是示例,需要换成检查到的实际路径。
如果大文件属于数据库、照片原图、用户上传文件或备份,应通过应用提供的清理、归档或备份保留策略处理。数据库数据文件尤其不能直接按大小删除。
不要手动删除 Docker 内部的镜像层目录,也不要把没有容器引用的数据卷直接视为垃圾。
六、docker system prune会删除哪些内容?
docker system prune 会同时清理多类资源。执行前,需要理解不同参数带来的范围变化:
| 命令 | 主要清理范围 |
|---|---|
docker system prune | 已停止的容器、未使用的网络、悬空镜像和未使用的构建缓存 |
docker system prune -a | 在上述范围上,将镜像清理扩大到所有没有容器引用的镜像 |
docker system prune --volumes | 在默认范围上,增加未使用匿名卷的清理 |
默认不清理数据卷,并不意味着整个命令没有数据风险:已停止容器的可写层,也可能保存着没有备份的文件。
此外,清理命令通常提示的是删除类别,并不提供完整的逐项预览。因此,日常维护更适合先定位占用,再按镜像、缓存和废弃容器分别处理。
七、清理后检查空间和业务状态
完成对应清理后,再次查看:
df -hT
docker system df
docker ps --format 'table {{.Names}}\t{{.Status}}'
对比同一个文件系统的剩余空间,并打开实际网站或应用,检查关键功能。
如果释放空间很少,常见原因包括:镜像层仍被其他对象共享、占用来自正在使用的数据卷,或者空间主要消耗在日志和宿主机挂载目录。
后续维护时,应为日志设置轮转、为备份设置保留周期,并持续关注业务数据所在文件系统的容量。清理旧镜像和缓存能够回收闲置空间,持续增长的业务数据则需要单独规划。







