Docker镜像无法删除的解决方法

前言

删除镜像报错

1
Error response from daemon: reference does not exist

通常意味着 Docker 的内部元数据出现了不一致。

简单来说,Docker 的镜像列表里记录着某个镜像的存在,但当它试图去底层存储中查找并删除该镜像的具体文件时,却发现文件已经不见了或路径对不上。

这种情况常见于 Docker 升级后、非正常关机、或者手动修改了 /var/lib/docker 目录下的文件后。

清理构建缓存和悬空镜像

有时候,这个错误是由构建缓存中的残留引用引起的。尝试清理这些缓存可能会解决问题。

清理悬空镜像(dangling images):

1
docker image prune

清理构建缓存(Docker 20.10+):

1
docker builder prune

再次尝试删除:
执行完上述命令后,再次尝试删除报错的镜像。

强制删除

虽然这个错误通常表示元数据丢失,但有时强制删除命令能触发 Docker 重新检查依赖关系。

1
docker rmi -f <镜像ID或名称>

如果这条命令依然报同样的错误,说明问题确实出在元数据文件上,请继续往下看。

修复 repositories.json 文件

Docker 在 /var/lib/docker/image/ 下维护了一个 repositories.json 文件来记录镜像引用关系。

如果这个文件损坏或包含无效路径或无法访问路径,就会报这个错。

我这里使用这种方法解决了。猜测是国内无法访问docker.io导致的。

操作步骤:

备份并编辑 repositories.json

建议先备份:

1
sudo cp /data/tools/docker/image/overlay2/repositories.json /data/tools/docker/image/overlay2/repositories.json.bak

注意我这里更改了路径,默认路径是 /var/lib/docker/image/overlay2/repositories.json

下载

1
/data/tools/docker/image/overlay2/repositories.json

修复方法:
检查文件中是否有指向 docker.io/ 的条目,或者寻找与报错镜像相关的条目。

将文件中所有的 docker.io/ 替换为空字符串 "" 可以解决问题,或者直接删除报错镜像对应的 JSON 块。

最好是把文件下载到本地,使用编辑器中替换字符串,防止替换后有相同名称的。

VSCode中查看JSON有相同的Key的时候会显示警告线,方便发现删除后重复的键。

如果有相同名称的删除不用的镜像对应的 JSON 块。

重启 Docker 服务

1
sudo systemctl restart docker

再次尝试删除
此时 Docker 会重新加载元数据,通常就可以正常删除了。

彻底重置

如果上述方法都太复杂或者无效,且你不在乎丢失当前的镜像和容器数据,可以重置 Docker 的数据目录。

警告:

这将删除你所有的镜像、容器和卷!

操作

1
2
3
sudo systemctl stop docker
sudo rm -rf /var/lib/docker
sudo systemctl start docker