Docker 磁盘空间不足?从排查到根治的完整方案

主题: docker-no-space-left-on-device-fix更新于: 2026/6/26作者:AgentFactory 技术团队

No space left on device 是 Docker 用户最常遇到的错误之一。但很多时候,df -h 显示磁盘还有空间,错误却照报不误。本文从根因分析到解决方案,覆盖手动清理、自动脚本、磁盘扩容三个层次,帮你彻底解决这个问题。

问题复现与根因分析

典型报错场景

当你执行 docker builddocker pulldocker run 时,突然遇到:

Error: No space left on device

但运行 df -h 却发现磁盘使用率并不高(例如只有 60%)。这时问题往往不在磁盘块空间,而在 inode 耗尽

根因一:inode 耗尽

Docker 的构建缓存和 overlay2 存储层会产生大量小文件。每个文件占用一个 inode,当 inode 数量达到上限时,即使磁盘还有剩余空间,也无法创建新文件。

排查命令:

BASH
df -i

如果 IUsed 列接近 IFree 的总和(使用率 100%),说明 inode 已耗尽。

根因二:Docker 存储驱动配额限制

某些存储驱动(如 devicemapper)有独立的存储池配额。即使宿主机文件系统有空闲空间,Docker 的存储池也可能已满。

根因三:Docker 守护进程文件锁定

在 Docker 守护进程繁忙时(如正在执行 docker commitdocker save),清理操作可能因文件锁定而失败。这属于偶发问题,重启 Docker 服务通常可解决。

安全清理:分层策略

不要一上来就执行 docker system prune -a --volumes,这会删除所有未使用的容器、镜像、网络和卷,可能导致构建缓存丢失,增加后续构建时间,甚至误删重要数据。

第一层:查看空间使用情况

BASH
docker system df

该命令会显示镜像、容器、本地卷和构建缓存分别占用了多少空间。

第二层:定向清理(推荐)

清理目标命令说明
停止超过 24 小时的容器docker container prune --filter until=24h保留最近停止的容器,方便回滚
悬空镜像(无标签且无关联容器)docker image prune --filter dangling=true安全,不会误删正在使用的镜像
构建缓存(保留指定大小)docker builder prune --keep-storage 5GB在释放空间和保持构建速度之间取得平衡
未使用的卷docker volume prune谨慎使用,卷可能包含持久化数据

最佳实践组合:

BASH
# 安全清理脚本(适合生产环境)
docker container prune --filter until=24h -f
docker image prune --filter dangling=true -f
docker builder prune --keep-storage 5GB -f

第三层:激进清理(仅用于本地开发环境)

BASH
# 删除所有未使用的容器、网络、镜像和卷
docker system prune -a --volumes -f

风险提示: 此命令会删除所有未被运行中容器使用的镜像和卷,可能导致后续构建需要重新下载所有基础镜像。

根治方案:磁盘扩容

如果清理后空间仍然不足,或者你希望从根本上解决问题,最推荐的做法是扩展底层块设备的大小。

云服务器磁盘扩容步骤

  1. 在云控制台扩展磁盘(例如从 20GB 扩展到 50GB),具体操作请以云服务商文档为准。

  2. 登录服务器,扩展分区:

    BASH
    # 安装 growpart(如果未安装)
    sudo apt-get install cloud-guest-utils  # Ubuntu/Debian
    sudo yum install cloud-utils-growpart   # CentOS/RHEL
    
    # 扩展分区(假设磁盘为 /dev/sda,分区号为 1)
    sudo growpart /dev/sda 1
    
  3. 扩展文件系统:

    BASH
    sudo resize2fs /dev/sda1
    
  4. 验证结果:

    BASH
    df -h
    

注意事项:

  • 如果 growpart 报错 partition is busy,需要先卸载分区:sudo umount /dev/sda1(如果无法卸载,可能需要重启进入单用户模式)。
  • 磁盘扩容操作前必须备份数据
  • 此方法无需修改 Docker 配置,且能从根本上解决空间不足问题。

常见报错与排查

报错 1:df -h 显示有空间,但 Docker 报错

排查步骤:

  1. 检查 inode:df -i
  2. 如果 inode 耗尽,执行 docker builder prune 清理构建缓存中的大量小文件
  3. 检查 Docker 存储驱动配额:docker info | grep -i "storage"

报错 2:docker system prune -a 后构建变慢

原因: 所有构建缓存被删除,后续构建需要重新下载和编译。

解决方案: 使用 docker builder prune --keep-storage 10GB 替代,保留最近 10GB 的缓存。

报错 3:docker rm $(docker ps -a -q) 报错

You cannot remove a running container

解决方案: 先停止所有容器,再删除:

BASH
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)

或者强制删除:

BASH
docker rm -f $(docker ps -a -q)

常见问题 FAQ

Q: 为什么 df -h 显示磁盘还有空间,但 Docker 仍然报 'No space left on device'?

A: 最常见的原因是 inode 耗尽。首先检查 df -i。如果 inode 使用率达到 100%,即使磁盘块有剩余空间也无法创建新文件。另一个原因是 Docker 的存储池(如 devicemapper)已满,但文件系统层面仍有空间。解决方案是清理 Docker 的构建缓存和未使用的镜像/容器。

Q: 如何在不影响生产服务的情况下安全地清理 Docker 空间?

A: 安全清理策略:

  1. 使用 docker system df 先查看空间使用情况。
  2. 使用 docker container prune --filter until=24h 只删除 24 小时前停止的容器。
  3. 使用 docker image prune --filter dangling=true 只删除悬空镜像。
  4. 使用 docker builder prune --keep-storage 5GB 保留 5GB 的构建缓存。
  5. 避免使用 docker system prune -a --volumes,因为它会删除所有未使用的卷,可能导致数据丢失。

Q: 在云服务器上,最推荐的永久性解决方案是什么?

A: 最推荐的永久性解决方案是扩展底层块设备的大小。具体步骤:1. 在云控制台扩展磁盘大小(如从 20GB 扩展到 50GB)。2. 登录服务器,使用 growpart 扩展分区(如 growpart /dev/sda 1)。3. 使用 resize2fs 扩展文件系统(如 resize2fs /dev/sda1)。此方法无需修改 Docker 配置,且能从根本上解决空间不足问题。


参考链接:

相关深度解决方案

在配置当前服务时,如果您遇到了数据库锁死或需要更高并发的读写控制,建议配合参考我们整理的 SQLite MCP 服务的高级缓存配置指南 来提升响应速度。