上周五晚上我正在撸代码,突然收到疯狂报警,服务器 / 分区使用率 92%!”。

登录服务器一看,根目录确实快满了,但 /data(挂载在 vdb 上)还有大把空闲。但是我早就把 Docker 的 data-root 迁到 vdb 上了,怎么系统盘还是被撑爆了?

df -h 看了一眼,overlay 挂载点确实显示在 vdb 上,空间还很充裕。但 du -sh / 一查,根目录下 /var/lib/containerd 赫然占了 24GB

overlay挂载目录和实际存储目录不在同一个地方,这什么情况,之前的服务器都没有出现过这个情况。


一、问题检查

# 明明设了 data-root 到 /data/docker
$ docker info | grep "Docker Root Dir"
Docker Root Dir: /data/docker

# df 看 overlay 也是 vdb 设备
$ df -h | grep overlay
overlay          100G   20G   80G  20% /var/lib/docker/overlay2/xxx/merged

# 但根分区还是被吃光
$ df -h /
/dev/vda1        50G   46G   4G  92% /

二、排查过程:初步估计是版本的问题

第一步:确认 Docker 到底把数据写哪了

docker info 给的 Docker Root Dir/data/docker,没错。我又去 /data/dockerdu -sh 一看,只有 2.4GB。那剩下的 40 多 GB 去哪了?

第二步:发现“真凶”

顺着 /var/lib 往下翻,/var/lib/containerd 竟然有 24GB。再仔细看,里面有个 io.containerd.snapshotter.v1.overlayfs 目录,全是镜像层数据。

按这个关键字去查找,确实发现了原因,新版本的docker的存储,换地方了,甚至不是用同一个存储方式了。

本质原因

新版的docker的底层也逐渐迁移到container上了。

三、解决方案:让 Containerd 也“搬家”

既然问题根源是 containerdroot 目录还在系统盘,那就把它也迁到数据盘(vdb)上。

方案选择:mv 还是 rsync

我测试了下,跨盘移动大文件夹mvrsync 的本质都是“复制+删除”。但 rsync 支持断点续传和进度显示,尤其在生产环境,我强烈推荐用 rsync,虽然稍慢一点,但安心。

操作步骤

1. 停止一切容器和服务

docker stop $(docker ps -aq)
systemctl stop docker containerd

重要! 必须停 containerd,否则文件被占用,迁移会失败。

2. 创建新目录并同步数据

mkdir -p /data/containerd
rsync -avP --remove-source-files /var/lib/containerd/ /data/containerd/

--remove-source-files 是传完一个删一个,类似 mv 的效果,但更安全。

3. 修改 containerd 配置

新建配置文件:

touch /etc/containerd/config.toml

写入

root = "/data/containerd"

4. 启动服务并验证

systemctl start containerd docker

检查是否生效:

ps aux | grep containerd | grep root
# 应该看到 --root /data/containerd

确认所有容器正常,然后删除旧目录备份,检查磁盘释放成功,

rm -rf /var/lib/containerd
df -ah

四、深入原理:为什么 Docker 要搞这么复杂?

很多朋友可能还停留在“Docker 所有东西都在 /var/lib/docker”的印象里。其实从 Docker 1.11(2016 年) 开始,Docker 就把底层容器运行时抽离成了 containerd,并独立管理镜像快照。

更“刺激”的是,从 Docker 29 版本开始,镜像存储彻底移入 containerd/var/lib/docker 只剩元数据了。但升级不会自动迁移,所以如果你从 27 升到 29,老数据还在老地方,新镜像才进新目录,会造成更混乱的局面。

这就好比公司搬家,老员工还坐老工位,新员工去新工位,行政不管,乱成一锅粥。

因此,无论你用的是哪个 Docker 版本,只要发现系统盘空间异常,第一件事就是检查 /var/lib/containerd 的大小


五、总结 + 避坑指南

检查点 命令 预期
Docker 根目录 docker info | grep "Docker Root Dir" 应在数据盘
Containerd 根目录 ps aux | grep containerd | grep root 应在数据盘
磁盘占用分布 du -sh /var/lib/containerd /var/lib/docker 两者都在数据盘
升级后存储驱动 docker info | grep "Storage Driver" 若为 overlay2 则还是旧模式,如需新模式需手动启用 features.containerd-snapshotter

新装服务器时,第一步就把 Docker 和 Containerd 的根目录都配置到数据盘。