在长时间运行Docker时,系统中存在大量的镜像。如何一次安全地删除所有未使用的Docker映像以释放存储空间?
另外,我还想删除几个月前拉的图片,这些图片有正确的TAG。
因此,我并不是只要求删除未标记的图像。我正在寻找一种方法来删除一般不使用的图像,其中包括未标记和其他图像,如几个月前拉正确的TAG。
在长时间运行Docker时,系统中存在大量的镜像。如何一次安全地删除所有未使用的Docker映像以释放存储空间?
另外,我还想删除几个月前拉的图片,这些图片有正确的TAG。
因此,我并不是只要求删除未标记的图像。我正在寻找一种方法来删除一般不使用的图像,其中包括未标记和其他图像,如几个月前拉正确的TAG。
当前回答
要修剪所有的图像和卷以及 Docker系统剪枝-af——volumes
其他回答
docker rm `docker ps -aq`
or
docker rm $(docker ps -q -f status=exited)
如果你自己构建这些修剪过的映像(从其他一些较旧的基础映像),请谨慎使用上述基于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
几周前移除旧容器。
Docker rm $(Docker ps -a | grep "weeks" | awk '{打印$1;}”)
几周前删除旧图像。小心些而已。这将删除几周前创建的基本图像,但您的新图像可能会使用这些图像。
Docker rmi $(Docker images | grep 'weeks' | awk '{打印$3;}”)
(原答案见下文)
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容器和图像垃圾收集脚本。 超过一小时前离开的集装箱被移除。 删除之后不属于任何剩余容器的图像。
请参阅docker系统修剪的官方参考
Docker系统修剪将删除:
所有停止的集装箱 所有网络不被至少一个容器使用 所有悬挂的图像 所有构建缓存
Docker系统prune -a也会做同样的事情,但是除了删除所有悬浮图像之外,它还会更广泛地删除:
没有至少一个与之关联的容器的所有映像
什么是悬空图像?
Docker映像由多个层组成,当从Dockerfile生成整个容器映像时,这些层被包装在父“容器层”中。悬浮图像是与任何其他标记图像没有关系的层,因此在任何构建的新容器中都不会有任何用途。它们不再起作用,而是消耗磁盘空间。
例如,悬浮图像可以通过以下过程创建:
从Dockerfile中构建一个命名image my-image,不指定任何标签:
FROM ubuntu:latest
CMD ["echo", "Hello World"]
docker build -t my-image
docker images
REPOSITORY TAG IMAGE ID
my-image latest 7ed6e7202eca <--- created, not dangling
ubuntu latest 825d55fb6340
更新Dockerfile:
FROM ubuntu:latest
CMD ["echo", "Hello, World!"]
使用以前的名称重新构建映像,不指定任何标记:
docker build -t my-image
docker images
REPOSITORY TAG IMAGE ID
my-image latest da6e74196f66 <--- replacement layer
<none> <none> 7ed6e7202eca <--- previous layer, now dangling
ubuntu latest 825d55fb6340
构建创建了一个新的my-image层。正如我们所看到的,最初创建的层仍然在那里,但它的名称和标签被设置为<none>:<none>。这个层永远不可能与任何docker容器层相关联,这意味着它是“悬空的”。
没有至少一个关联容器的图像是什么?
未使用的映像意味着它没有被分配或在容器中使用。例如,docker ps -a将列出所有运行和停止的容器。这些容器使用的任何映像都是“已用映像”。
当运行docker系统prune -a时,它将删除未使用和悬挂的图像。与至少一个容器相关联的任何映像都不会受到影响。