起因
我的 armbian 安装的是 docker-ce,而不是内置的 docker.io。这是 docker 官方推荐的,好处是更新快,有很多新的功能。但在某次更新后,用 docker system prune -a 不能清理无用的镜像了。
分析
通过查资料、问 AI,docker 官方从 v29 开始默认启用配置 containerd image store(容器镜像存储后端),而不再完全依赖旧的 overlay2 graph driver。即现在下载的镜像目录存储在 /var/lib/containerd/io.containerd.content.v1.content/blobs/sha256/ 目录下,而不再是 /var/lib/docker/overlay2/ 目录下。通过以下命令验证:

也可以用 docker info | grep -i -E "storage|snapshotter|driver|root dir" 查看。如果文件系统是 overlay2 是 docker 控制(旧模式),文件系统是 overlayfs 是 containerd 控制(新模式)。
现在,docker system prune -a 只会对不再使用镜像去掉标签,保留再系统内作为缓存,而不是直接删除。而进一步的操作交给更底层的 containerd。
containerd 使用 leases (租期)来“锁定”某些资源,防止它们在垃圾回收(GC)时被删除。只要在租期内,关联的资源就被认为是“正在使用中”,即使镜像被 untagged 或看起来 unused,也不会被释放。如图,它定义了一个过期时间,到时候会自动释放。
可以用 ctr -n moby leases ls 查看,其中的 moby 是 dockers 默认的命名空间。

处理
有两个选择——
保持
适应新特性,什么都不用做,让它自动管理。
回退
如果想回到旧模式,编辑 /etc/docker/daemon.json:
{
"features": {
"containerd-snapshotter": false
}
}
然后 systemctl restart docker。


