在长时间运行Docker时,系统中存在大量的镜像。如何一次安全地删除所有未使用的Docker映像以释放存储空间?

另外,我还想删除几个月前拉的图片,这些图片有正确的TAG。

因此,我并不是只要求删除未标记的图像。我正在寻找一种方法来删除一般不使用的图像,其中包括未标记和其他图像,如几个月前拉正确的TAG。


当前回答

@VonC已经给出了一个非常好的答案,但为了完整起见,这里有一个我一直在使用的小脚本——如果你有一些差事,它也会破坏任何Docker进程:

#!/bin/bash

imgs=$(docker images | awk '/<none>/ { print $3 }')
if [ "${imgs}" != "" ]; then
   echo docker rmi ${imgs}
   docker rmi ${imgs}
else
   echo "No images to remove"
fi

procs=$(docker ps -a -q --no-trunc)
if [ "${procs}" != "" ]; then
   echo docker rm ${procs}
   docker rm ${procs}
else
   echo "No processes to purge"
fi

其他回答

第二次更新(2017-07-08)

参考(再次)VonC,使用更近期的系统修剪。不耐烦的人可以使用-f,——force选项跳过提示符:

docker system prune -f

没有耐心和鲁莽的人还可以使用-a,——all选项删除“未使用的图像,而不仅仅是悬垂的图像”:

docker system prune -af

https://docs.docker.com/engine/reference/commandline/system_prune/

更新

参考VonC的答案,它使用了最近添加的修剪命令。下面是对应的shell别名方便:

alias docker-clean=' \
  docker container prune -f ; \
  docker image prune -f ; \
  docker network prune -f ; \
  docker volume prune -f '

旧的答案

删除停止(退出)的容器:

$ docker ps --no-trunc -aqf "status=exited" | xargs docker rm

删除未使用的(悬空的)图像:

$ docker images --no-trunc -aqf "dangling=true" | xargs docker rmi

如果您对不可撤销的数据丢失非常谨慎,那么您可以删除未使用的(悬空)卷(v1.9及以上版本):

$ docker volume ls -qf "dangling=true" | xargs docker volume rm

下面是一个方便的shell别名:

alias docker-clean=' \
  docker ps --no-trunc -aqf "status=exited" | xargs docker rm ; \
  docker images --no-trunc -aqf "dangling=true" | xargs docker rmi ; \
  docker volume ls -qf "dangling=true" | xargs docker volume rm'

参考文献

Docker ps -f 码头工人rm Docker images -f 码头工人rmi Docker v1.9.0版本说明 Docker卷ls Docker卷rm

docker rm `docker ps -aq`

or

docker rm $(docker ps -q -f status=exited)

要删除超过一个月的旧标记图像:

$ docker images --no-trunc --format '{{.ID}} {{.CreatedSince}}' \
    | grep ' months' | awk '{ print $1 }' \
    | xargs --no-run-if-empty docker rmi

注意,它将无法删除容器使用的图像,在存储库中引用,有依赖的子图像…这可能是你想要的。否则只需添加-f标志。

/etc/cron.示例每日/ docker-gc脚本:

#!/bin/sh -e

# Delete all stopped containers (including data-only containers).
docker ps -a -q --no-trunc --filter "status=exited" | xargs --no-run-if-empty docker rm -v

# Delete all tagged images more than a month old
# (will fail to remove images still used).
docker images --no-trunc --format '{{.ID}} {{.CreatedSince}}' | grep ' months' | awk '{ print $1 }' | xargs --no-run-if-empty docker rmi || true

# Delete all 'untagged/dangling' (<none>) images
# Those are used for Docker caching mechanism.
docker images -q --no-trunc --filter dangling=true | xargs --no-run-if-empty docker rmi

# Delete all dangling volumes.
docker volume ls -qf dangling=true | xargs --no-run-if-empty docker volume rm

如果你有很多这样的图像,移除它们可能真的很乏味,但幸运的是Docker有几个命令可以帮助我们消除悬浮图像。在旧版本的Docker中(这在今天仍然有效),你可以通过运行Docker rmi -f $(Docker images -f " hanging =true" -q)来删除悬浮图像。

(原答案见下文)


2016年9月更新:Docker 1.13: PR 26108和commit 86de7c0引入了一些新命令,以帮助方便地可视化Docker守护进程数据在磁盘上占用了多少空间,并允许轻松清理“不需要的”多余空间。

docker系统修剪将删除所有悬空数据(即:容器停止,卷没有容器和图像没有容器)。即使是未使用的数据,使用-a选项。

你还有:

码头集装箱修剪 Docker映像修剪 Docker网络修剪 码头卷修剪

对于未使用的图像,使用docker image prune -a(用于删除悬空和未使用的图像)。 警告:'unused'表示“未被任何容器引用的图像”:在使用-a之前要小心。

正如A L的回答所示,docker系统prune -all将删除所有未使用的图像,而不仅仅是悬垂的图像…这可能有点太多了。

结合docker xxx prune和——filter选项可以是限制修剪的好方法(docker SDK API最低1.28,所以docker 17.04+)

目前支持的过滤器有:

Until (<timestamp>) -只删除在给定时间戳之前创建的容器、图像和网络 Label (Label =<key>, Label =<key>=<value>, Label !)=<key>, or label!=<key>=<value>) -仅删除带有(或没有,以防标签!=…使用)指定的标签。

有关示例,请参见“修剪图像”。


警告:docker xxx prune命令没有“预览”或“——dry-run”选项。

自2017年以来,moby/moby issue 30623要求这样做,但似乎很难实施(2022年8月)

Having a more representative overview of what will be pruned will be quite complicated, for various reasons; race conditions (can be resolved by documenting the limitations); A container/image/volume/network may not be in use at the time that "dry run" is used, but may be in use the moment the actual prune is executed (or vice-versa), so dry run will always be an "approximation" of what will be pruned. the more difficult part is due to how objects (containers, images, networks etc.) depend on each other. For example, an image can be deleted if it no longer has references to it (no more tags, no more containers using it); this is the reason that docker system prune deletes objects in a specific order (first remove all unused containers, then remove unused images). In order to replicate the same flow for "dry-run", it will be needed to temporarily construct representation of all objects and where they're referenced based on that (basically; duplicate all reference-counters, and then remove references from that "shadow" representation). Finally; with the work being done on integrating the containerd snapshotter (image and layer store), things may change more; For example, images can now be multi-arch, and (to be discussed), "pruning" could remove unused variants (architectures) from an image to clean up space, which brings another dimension to calculating "what can be removed".


原答案(2016年9月)

我通常这样做:

docker rmi $(docker images --filter "dangling=true" -q --no-trunc)

我有一个[别名删除这些悬空图像:drmi]13

悬空=true过滤器发现未使用的图像

这样,任何不再被标记图像引用的中间图像都将被删除。

我首先对退出的进程(容器)执行相同的操作

alias drmae='docker rm $(docker ps -qa --no-trunc --filter "status=exited")'

haridsv在评论中指出:

从技术上讲,在清理图像之前应该先清理容器,因为这样可以捕获更多悬空图像并减少错误。


Jess Frazelle (jfrazelle)有bashrc函数:

dcleanup(){
    docker rm -v $(docker ps --filter status=exited -q 2>/dev/null) 2>/dev/null
    docker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2>/dev/null
}

要删除旧图像,而不仅仅是“未引用的悬空”图像,你可以考虑docker-gc:


一个简单的Docker容器和图像垃圾收集脚本。 超过一小时前离开的集装箱被移除。 删除之后不属于任何剩余容器的图像。