适用:使用 systemd 的 Linux 服务器、常规 rootful Docker Engine;Compose 示例使用
docker composeV2。本文为教学故障场景,错误文本和结果为示意,具体输出以现场为准。
一、遭遇情况:拉镜像失败,应用也开始写不进文件
服务器部署时报 no space left on device,容器内应用也出现写入失败。有人准备执行 docker system prune -a --volumes,希望一次清干净。
本篇案例设定为某 Web 容器持续输出大量日志,使用的 json-file 日志没有配置大小限制,导致相关文件系统空间耗尽。排查仍需先区分容量、inode、日志、镜像和业务数据,不能预先认定全是“无用容器”。
二、原因分析:报错不只等于磁盘字节用完
文件系统容量耗尽会写不进数据;inode 耗尽时,即使还有容量,也可能无法新建文件。还有配额、其他挂载点或应用自己的数据目录,不能只检查根分区。
Docker 镜像层、容器可写层、卷和日志含义不同。业务卷看起来很大,也可能保存着唯一的数据库数据;未使用镜像也可能是回滚资源,不等于可以随意删除。

三、排查思路:从文件系统到具体对象
1. 检查容量、inode 和实际数据目录
df -h
df -i
docker info --format 'DockerRootDir={{.DockerRootDir}}'
docker system df -v
如果 daemon 因磁盘满已不可用,先检查主机文件系统与服务配置,不要把 docker 命令失败当作没有数据。DockerRootDir 不保证涵盖所有存储位置;使用 containerd image store 的安装还可能有独立的 containerd 存储,卷也可能位于其他磁盘。
在已经确认的目标文件系统上用 du -xhd1 逐级定位大目录,例如默认数据目录确为 /var/lib/docker 时:
sudo du -xhd1 /var/lib/docker
-x 尽量避免跨文件系统统计。大目录扫描会产生 I/O,不要在高负载时无目的地全盘遍历。镜像层有共享关系,docker system df 的数值不能简单与所有目录大小逐项相加。
2. 检查可疑容器的日志驱动
假设异常容器名为 web:
docker inspect web --format '{{json .HostConfig.LogConfig}}'
docker inspect web --format '{{.LogPath}}'
docker logs --tail 100 --timestamps web
确认是否为 json-file,是否缺少轮转参数,日志是否在重复输出异常。日志很大通常还要追问为何持续刷屏:重启循环、错误重试和不合适的日志级别都可能是源头。
Docker 官方要求日志文件由 daemon 管理。不要直接删除或截断 Docker 活跃日志文件作为常规修复,也不要手工删除 overlay2 或容器元数据目录。
四、修复实践:先恢复可操作空间,再修增长来源
如果文件系统已经完全写满,优先评估扩容,或按服务器现有保留策略处理已经确认可清理的其他文件。释放少量空间后再做受控容器维护,比在无法创建任何文件的环境里反复部署更可靠。
若确认是构建缓存占用,可在核对当前 builder 和缓存用途后有目标地清理。缓存清理、镜像清理与数据卷清理后果不同;本篇不提供一个可盲目执行的全局“清空命令”。
对需要持续运行的 Web 服务,修正应用的刷屏问题,并在 Compose 中配置日志轮转:
services:
web:
image: nginx:stable-alpine
ports:
- "127.0.0.1:18091:80"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
10 MiB 和 3 个文件是教学示例,实际根据日志采集、保留要求和磁盘容量确定。它也不是精确的“整个容器磁盘上限”:业务文件、可写层和其他驱动存储仍需单独管理。
为什么改完配置,旧日志还是继续涨
日志配置是在容器创建时确定的。修改 daemon 默认值或 Compose 文件后,仅 docker restart web 不会把已有容器更新为新的日志配置。
先确认业务数据已经正确挂载、原日志需要保留的部分已采集,以及服务允许重建,再按部署流程重建目标服务。例如在正确项目目录:
docker compose config
docker compose up -d --force-recreate web
docker compose ps
不要为了重建一个服务执行 docker compose down -v,那会把数据卷也纳入删除范围。原容器可写层中的数据也不会自然跟到新容器,必须先核对。
五、验证:既看可用空间,也看增长速度
docker inspect "$(docker compose ps -q web)" --format '{{json .HostConfig.LogConfig}}'
df -h
df -i
docker compose logs --tail 50 web
确认新容器的 LogConfig 中确实有大小和数量参数,再观察业务请求与日志增长。配上轮转只解决单容器日志增长的一部分问题,异常刷屏仍应修复,采集端和宿主机其他日志也要纳入容量监控。
六、总结:清理前先知道数据属于谁
证据链是:哪个文件系统 → 容量还是 inode → 哪类对象 → 哪个持续增长源 → 有目标地恢复与限制。真正的修复既要让服务器重新可写,也要让相同问题不再悄悄积累。