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

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

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


当前回答

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

$ 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 rmi $(docker images | grep "^<none>" | awk "{print $3}")

@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

首先,运行docker images查看图像列表,并将IMAGE HASH ID复制到剪贴板中。

运行docker rmi -f <镜像>

记住选项-f是强制删除。

如果你自己构建这些修剪过的映像(从其他一些较旧的基础映像),请谨慎使用上述基于docker image prune的可接受解决方案,因为该命令是生硬的,并将尝试删除最新映像所需的所有依赖关系(该命令可能应该重命名为docker image*s* prune)。

我为我的docker映像构建管道(其中有每日构建和标签=日期YYYYMMDD格式)提出的解决方案是:

# carefully narrow down the image to be deleted (to avoid removing useful static stuff like base images)
my_deleted_image=mirekphd/ml-cpu-py37-vsc-cust

# define the monitored image (tested for obsolescence), which will be usually the same as deleted one, unless deleting some very infrequently built image which requires a separate "clock"
monitored_image=mirekphd/ml-cache

# calculate the oldest acceptable tag (date)
date_week_ago=$(date -d "last week" '+%Y%m%d')

# get the IDs of obsolete tags of our deleted image
# note we use monitored_image to test for obsolescence
my_deleted_image_obsolete_tag_ids=$(docker images --filter="before=$monitored_image:$date_week_ago" | grep $my_deleted_image | awk '{print $3}')

# remove the obsolete tags of the deleted image
# (note it typically has to be forced using -f switch)
docker rmi -f $my_deleted_image_obsolete_tag_ids

(原答案见下文)


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容器和图像垃圾收集脚本。 超过一小时前离开的集装箱被移除。 删除之后不属于任何剩余容器的图像。