「Docker」- 删除镜像

更新日期:2019年08月09日

内容简介

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

删除远程镜像

在镜像仓库(如Docker Hub中)中的镜像,要在镜像仓库中删除,目前不能通过命令删除。

通常是通过单击按钮来操作完成的,不涉及特别复杂的内容,所以简单略过。

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

删除本地镜像


# 删除镜像

使用docker rmidocker image rm命令来删除镜像,但是只能删除本地镜像,不能删除镜像仓库中的镜像。

从主机中删除镜像,并删除标签。如果镜像具有多个标签,则使用此命令,并且将标签作为参数,则仅删除标签。如果标签是镜像的唯一标签,则镜像和标签都将被删除。

除非使用-f选项,否则无法删除正在运行的容器的镜像。并且,使用-f选项,如果使镜像有多个标签,则会删除所有标签,并且也会删除镜像。

简单示例:

#!/bin/sh

# 通过Image ID删除
docker rmi fd484f19954f

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

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

选项-f值得一提。当一个镜像有多个标签的时候,如果使用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 -f fd484f19954f

该选项会取消所有标签,并删除镜像。并且有在运行的容器的镜像也可以通过-f选项删除。

# 删除“一批”镜像

如果要删除所有镜像可以使用:

#!/bin/sh

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

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

还可以配合grep等命令,进行过滤(关于过滤,命令docker images--filter选项,可以进行更加高级的过滤)

常见错误处理


# 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

该错误提示删除的镜像有依赖的子镜像。

解决办法:

#!/bin/sh

################################################################################
# 一个简单的做法
################################################################################
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>"

参考文献


ToC

内容简介

删除远程镜像

删除本地镜像

# 删除镜像

# 删除“一批”镜像

常见错误处理

# image has dependent child images

参考文献