Docker devicemapper 磁盘只涨不降:/mnt/docker/devicemapper/devicemapper 占用 13G 问题排查与解决

10次阅读
没有评论

前言

很多老服务器(典型 CentOS7 环境)Docker 默认存储驱动是 devicemapper,而且大多是 loop-lvm 模式。你会遇到一个很诡异的现象: 执行完 docker system prune -a 清理镜像、容器之后,docker system df 显示内部空间已经释放,但宿主上 du -sh /mnt/docker/devicemapper/devicemapper 看到的文件大小依然很高(例如 13G),不会自动缩小。

这不是清理命令没生效,是 devicemapper loop-lvm 本身的设计缺陷。

官方早已标记 devicemapper 为废弃(deprecated),新环境一律推荐 overlay2。

现象

13G     /mnt/docker/devicemapper/devicemapper

特征:

  1. docker system df 统计的镜像 / 容器占用远小于这个 13G;
  2. 反复 prune 清理,该文件体积不会回落;
  3. 它是稀疏文件,thin pool 内部空闲空间已经释放,但文件本身不会向操作系统归还磁盘块。

先区分两个概念

  • thin pool 内部空间:docker system df 看到的,prune 可以释放,Docker 后续拉镜像可以复用这块空间;
  • 宿主文件大小:du 看到的 /mnt/docker/devicemapper/devicemapper/data,loop-lvm 稀疏文件只膨胀、不自动收缩。

第一步:基础排查

# 确认存储驱动
docker info | grep -A10 "Storage Driver"

# 查看 thin pool 状态
dmsetup status | grep pool

# 查看docker内部资源占用概览
docker system df
# 明细
docker system df -v

第二步:常规清理(只能释放 Docker 内部池空间,不能缩文件)

先把无用资源清理干净,避免池内持续膨胀:

# 清理停止容器、悬空镜像、无用网络、构建缓存(不删volume)
docker system prune

# 清理所有未使用镜像(不仅仅悬空<none>镜像)
docker system prune -a

# 带时间过滤,清理7天未使用资源(推荐定时任务使用)
docker system prune -a --filter "until=168h"

# 分项清理命令
docker image prune -a
docker builder prune
docker container prune
docker network prune

⚠️ 注意:

  • docker system prune -a --volumes 会清理未被挂载的匿名卷,有丢数据风险,谨慎执行;
  • 命名持久化卷默认不会被 prune 删除;
  • 上面所有命令执行完,devicemapper/data 文件大小大概率还是 13G,这是正常现象。

补充:fstrim 只能回收容器文件系统内空闲块,无法缩小外层 devicemapper 稀疏文件,效果有限:

docker ps -q | xargs -I{} sh -c 'docker inspect --format {{.State.Pid}} {} | xargs -rIpid fstrim /proc/pid/root'

第三步:想要把 13G 文件瘦身还给系统(loop-lvm 停机重建方案)

⚠️ 高危操作,必须先备份重要持久化卷数据,会清空所有镜像、容器,需要停机。

# 1. 停止docker服务
systemctl stop docker
systemctl stop docker.socket

# 2. 备份目录(可选,防止翻车)
cp -r /mnt/docker/devicemapper /mnt/docker/devicemapper.bak

# 3. 删除devicemapper整个目录
rm -rf /mnt/docker/devicemapper

# 4. 启动docker,自动重建全新稀疏文件,初始体积很小
systemctl start docker

启动之后再重新拉镜像、启动业务,data 文件会按需缓慢增长,不会卡死在 13G。

第四步:根治方案,切换到 overlay2(强烈推荐)

devicemapper loop-lvm 本身就不适合长期运行,overlay2 不存在稀疏文件只涨不缩的问题,是当前主流稳定驱动。

操作步骤:

  1. 备份所有业务 volume 数据、导出需要保留的镜像
  2. 停止 docker
systemctl stop docker
  1. 修改 /etc/docker/daemon.json,指定存储驱动与数据根目录
{
  "storage-driver": "overlay2",
  "data-root": "/mnt/docker"
}
  1. 清理旧 devicemapper 数据(确认备份完成再删)
  2. 启动 docker
systemctl start docker
  1. 验证驱动
docker info | grep "Storage Driver"

输出 overlay2 即切换成功。

补充:loop-lvm vs direct-lvm

  • loop-lvm(当前场景):用两个稀疏文件模拟块设备,配置简单,缺点就是文件只增不减,适合测试,不建议生产长期使用;
  • direct-lvm:使用独立裸盘 / 分区作为 thin pool,性能更好,支持 lvextend 扩容,但同样不支持自动缩容,只是底层不是宿主上的大文件。

运维建议

  1. 老 CentOS7 机器优先迁移 overlay2,不要在 devicemapper 上反复折腾缩容;
  2. 可以配置定时 prune 脚本,定期清理无用镜像缓存,延缓膨胀;
  3. 生产环境禁止使用 loop-lvm;
  4. 不要随便使用 --volumes 参数清理卷,数据库等持久化数据优先使用命名 volume 单独备份。

小结

看到 /mnt/docker/devicemapper/devicemapper 占用十几 G 不要慌: prune 只能释放 Docker 内部 thin pool 空间;想要归还磁盘空间给宿主机,loop-lvm 只能停机重建目录;一劳永逸的办法是迁移到 overlay2 存储驱动。

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码