本笔记的内容包含:如何删除本地 Docker 镜像;如何删除远程 Docker 镜像;在删除过程中出现的常见问题的处理;还涉及了一些 Docker 镜像存储方式方面的内容。

删除远程镜像

在镜像仓库(如 Docker Hub 中)中的镜像,目前不能通过命令删除,要在镜像仓库中删除。通过单击按钮来完成删除操作,不涉及特别复杂的内容,所以简单略过。

# 08/08/2019 今天在 Docker v19.03 (current) 看到了 docker registry rmi 命令,可以从Registry中移除镜像,目前出于实验性质。

删除本地镜像

删除单个或多个镜像

使用 docker rmidocker image rm 命令来删除本地镜像(只能删除本地镜像,不能删除在镜像仓库中的镜像):

# 通过 Image ID 删除
docker rmi fd484f19954f

# 下面这两个是等价的,因为 latest 是默认的标签
docker rmi test1:latest
docker rmi test1

# 还可以通过 DIGEST 来删除。在 REPOSITORY 与 DIGEST之间,使用 @ 分隔。
# 因为使用 DIGEST 拉取的镜像是没有 TAG 的,所以会用到这种方法。
docker rmi test/busybox@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf

1)如果镜像具有多个标签,并且将标签作为删除参数,则命令仅删除标签;
2)如果镜像具有唯一标签,命令将删除标签,然后删除镜像;

删除被容器使用的镜像

如果镜像具有正在使用的容器,则无法删除,需要使用 -f 选项,将删除容器与镜像:

docker image rm --force "REPOSITORY:TAG"

删除所有镜像

如果要删除所有镜像可以使用如下命令(可以使用 docker images--filter 选项进行高级过滤):

# 下面的两个命令是等价的
docker image rm $(docker image ls -a -q)
docker rmi $(docker images -a -q)

# 删除有容器的镜像
docker image rm -f $(docker image ls -a -q)

删除 IMAGE ID 相同的所有镜像

当镜像具有多个标签时,如果使用 IMAGE ID 删除(docker rmi fd484f19954f),会产生如下错误:

Error: Conflict, cannot delete image fd484f19954f because it is tagged in multiple repositories, use -f to force 2013/12/11 05:47:16 Error: failed to remove one or more images

方法一、此时可以使用 -f 选项时,这将删除所有标签并删除镜像:

docker rmi --force fd484f19954f

方法二、使用命令 grep 进行过滤,将结果作为 docker rmi 参数以进行删除。

方法三、使用 docker inspect 命令,命令输出的 RepoTags 字段将显示相关标签,以用于删除。

常见错误处理

# image has dependent child images

Find the dependent child images on Docker

问题描述:
在删除某个镜像(docker rmi a990d6e2b083)的时候,提示如下错误:

Error response from daemon: conflict: unable to delete d86795370e7b (cannot be forced) - image has dependent child images

问题原因:
该错误提示删除的镜像有依赖的子镜像。

解决办法:

################################################################################
# 一个简单的做法
################################################################################
docker image inspect --format='{{.Id}} {{.Parent}}' \
    $(docker image ls --all --filter since=a990d6e2b083 -q) | grep a990d6e2b083

# 上述命令:
#1 (docker image ls)找到a990d6e2b083之后的镜像
#2 (docker image inspect)然后获取这些镜像的父镜像
#3 (grep)通过过滤父镜像,找到的就是引用该镜像的子镜像。

################################################################################
# 然而,问题从来就不是这么简单的
################################################################################
# 最大的问题在于:子镜像还有子镜像,慢慢找???
# 其实你要做的事情很简单。通常这个问题是由于有悬空镜像引用了该镜像,所以删除所有“悬空”的镜像即可。
# 「悬空镜像」可以放心的删除
docker rmi $(docker images --filter "dangling=true" -q --no-trunc)

################################################################################
# 但是,真正正确的做法是这样的
# 找到要删除镜像的子镜像的子镜像的子镜像…………(不多删,也不少删除)
# https://stackoverflow.com/questions/38118791/can-t-delete-docker-image-with-dependent-child-images/38119847#38119847#answer-53037893
################################################################################
recursive_remove_image() {
  for image in $(docker images --quiet --filter "since=${1}") # 找到这个镜像之后的镜像。因为子镜像是在这之后的。
  do
    if [ $(docker history --quiet ${image} | grep ${1}) ] # 查看这个子镜像的构建历史,是否包含了这镜像。如果是,那就应该删除。
    then
      recursive_remove_image "${image}" # 进行递归,删除应用这个镜像的子镜像。
    fi
  done
  # 执行删除
  echo "Removing: ${1}"
  docker rmi -f ${1}
}
recursive_remove_image "<image-id>"

参考文献

 

  • WikiNotes/删除镜像
  • Find the dependent child images on Docker
  • docker image rm
  • docker rmi
  • docker images
  • Can’t delete image with children
  • Can’t delete docker image with dependent child images
  • How To Remove Docker Images, Containers, and Volumes
  • How to remove multiple docker images with the same imageID?