如何删除旧的和未使用的Docker映像

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

此外,我还想删除几个月前提取的图像,这些图像具有正确的TAG

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

604501 次浏览

(原答案见下文)


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

#0将删除所有悬空数据(即按顺序:停止的容器、没有容器的卷和没有容器的图像)。即使是未使用的数据,有-a选项。

你也有:

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

a l回答所示,docker system prune --all将删除所有未使用图像,而不仅仅是悬挂的图像……这可能有点太多了。

docker xxx prune#1选项结合起来可能是限制修剪的好方法(docker SDK API最低1.28,因此docker 17.04+

目前支持的过滤器有:

  • until (<timestamp>)-仅删除在给定时间戳之前创建的容器、图像和网络
  • labellabel=<key>label=<key>=<value>label!=<key>label!=<key>=<value>)-仅删除带有(或没有,如果使用label!=...)指定标签的容器、图像、网络和卷。

例如,请参阅“修剪图像”。

原始答案(2016年9月)

我通常做:

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

我有一个[别名删除那些悬挂图像drmi]13

dangling=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/nulldocker rmi $(docker images --filter dangling=true -q 2>/dev/null) 2>/dev/null}

要删除旧图像,而不仅仅是“未引用的悬挂”图像,您可以考虑#0


一个简单的Docker容器和镜像垃圾回收机制脚本。

  • 一个多小时前离开的集装箱被移除。
  • 之后不属于任何剩余容器的图像将被删除。

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

#!/bin/bash
imgs=$(docker images | awk '/<none>/ { print $3 }')if [ "${imgs}" != "" ]; thenecho docker rmi ${imgs}docker rmi ${imgs}elseecho "No images to remove"fi
procs=$(docker ps -a -q --no-trunc)if [ "${procs}" != "" ]; thenecho docker rm ${procs}docker rm ${procs}elseecho "No processes to purge"fi

如果您想删除X个月前提取的图像,您可以尝试以下示例,其中删除三个月前创建的图像:

three_months_old_images=`docker images | grep -vi "<none>" | tr -s ' ' | cut -d" " -f3,4,5,6 | grep "3 months ago" | cut -d" " -f1`docker rmi $three_months_old_images
docker rm `docker ps -aq`

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

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

(再次)参考VonC,使用最近的system prune。不耐烦的人可以使用-f, --force选项跳过提示:

docker system prune -f

不耐烦和鲁莽还可以使用-a, --all选项删除“未使用的图像,而不仅仅是悬挂的图像”:

docker system prune -af

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

更新

请参阅VonC的回答,它使用最近添加的prune命令。这是相应的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 images --no-trunc --format '\{\{.ID}} \{\{.CreatedSince}}' \| grep ' months' | awk '{ print $1 }' \| xargs --no-run-if-empty docker rmi

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

/etc/cron.daily/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}")

我最近在我的一个服务器上写了一个脚本来解决这个问题:

#!/bin/bash
# Remove all the dangling imagesDANGLING_IMAGES=$(docker images -qf "dangling=true")if [[ -n $DANGLING_IMAGES ]]; thendocker rmi "$DANGLING_IMAGES"fi
# Get all the images currently in useUSED_IMAGES=($( \docker ps -a --format '\{\{.Image}}' | \sort -u | \uniq | \awk -F ':' '$2{print $1":"$2}!$2{print $1":latest"}' \))
# Get all the images currently availableALL_IMAGES=($( \docker images --format '\{\{.Repository}}:\{\{.Tag}}' | \sort -u \))
# Remove the unused imagesfor i in "${ALL_IMAGES[@]}"; doUNUSED=truefor j in "${USED_IMAGES[@]}"; doif [[ "$i" == "$j" ]]; thenUNUSED=falsefidoneif [[ "$UNUSED" == true ]]; thendocker rmi "$i"fidone

这是一个清理Docker镜像并回收空间的脚本。

#!/bin/bash -x## Removing stopped containerdocker ps -a | grep Exited | awk '{print $1}' | xargs docker rm
## If you do not want to remove all container you can have filter for days and weeks old like below#docker ps -a | grep Exited | grep "days ago" | awk '{print $1}' | xargs docker rm#docker ps -a | grep Exited | grep "weeks ago" | awk '{print $1}' | xargs docker rm
## Removing Dangling images## There are the layers images which are being created during building a Docker image. This is a great way to recover the spaces used by old and unused layers.
docker rmi $(docker images -f "dangling=true" -q)
## Removing images of perticular pattern For example## Here I am removing images which has a SNAPSHOT with it.
docker rmi $(docker images | grep SNAPSHOT | awk '{print $3}')
## Removing weeks old images
docker images | grep "weeks ago" | awk '{print $3}' | xargs docker rmi
## Similarly you can remove days, months old images too.

原始脚本

https://github.com/vishalvsh1/docker-image-cleanup

通常Docker将所有与图像构建和图层相关的临时文件保存在

/var/lib/docker

此路径是系统本地的,通常位于THE根分区"/"

您可以挂载更大的磁盘空间并将/var/lib/docker的内容移动到新的挂载位置并创建符号链接。

这样,即使Docker映像占用空间,也不会影响您的系统,因为它将使用其他挂载位置。

原文:管理本地磁盘上的Docker镜像

要删除未运行容器的标记图像,您必须使用一个小脚本:

#!/bin/bash
# remove not running containersdocker rm $(docker ps -f "status=exited" -q)
declare -A used_images
# collect images which has running containerfor image in $(docker ps | awk 'NR>1 {print $2;}'); doid=$(docker inspect --format="\{\{.Id}}" $image);used_images[$id]=$image;done
# loop over images, delete those without a containerfor id in $(docker images --no-trunc -q); doif [ -z ${used_images[$id]} ]; thenecho "images is NOT in use: $id"docker rmi $idelseecho "images is in use:     ${used_images[$id]}"fidone

偶尔我会遇到Docker分配并继续使用磁盘空间的问题,即使空间没有分配给任何特定的映像或现有容器。我意外产生这个问题的最新方式是使用“docker-Engine”centos构建而不是RHEL 7.1中的“docker”。似乎发生的情况是,有时容器清理没有成功完成,然后空间永远不会被重用。当我分配为/的80GB驱动器充满/var/lib/docker文件时,我必须想出一种创造性的方法来解决这个问题。

这是我想出的。首先要解决磁盘已满错误:

  1. 停止docker:systemctl stop docker

  2. 分配一个新的驱动器安装为/mnt/docker

  3. /var/lib/docker中的所有文件移动到/mnt/docker。我使用了命令:

    rsync -aPHSx --remove-source-files /var/lib/docker/ /mnt/docker/
  4. 将新驱动器挂载到/var/lib/docker

在这一点上,我不再有磁盘满错误,但我仍然浪费了大量的空间。接下来的步骤是处理这个问题。

  1. 启动Docker:systemctl start docker

  2. 保存所有图片:

    docker save $(docker images |sed -e '/^<none>/d' -e '/^REPOSITORY/d' -e 's,[ ][ ]*,:,' -e 's,[ ].*,,') > /root/docker.img
  3. 卸载docker。

  4. 删除/var/lib/docker中的所有内容:

    rm -rf /var/lib/docker/[cdintv]*
  5. 重新安装docker

  6. 启用docker:systemctl enable docker

  7. 启动docker:systemctl start docker

  8. 恢复图像:

    docker load < /root/docker.img
  9. 启动您需要运行的任何持久容器。

这将我的磁盘使用量从Docker的67 GB降至Docker的6 GB。

我不建议在日常使用中这样做。但当看起来docker因软件错误或意外重新启动而丢失了使用的磁盘空间时,运行它很有用。

如何删除标记的图像

  1. docker rmi标签第一

  2. docker rmi图像。

    #可以在一个docker rmi调用中完成,例如:#docker rmi

  3. 代码类型

(这适用于2016年11月,Docker版本1.12.2)

e. g.

$ docker imagesREPOSITORY              TAG                 IMAGE ID            CREATED             SIZEusrxx/the-application   16112805            011fd5bf45a2        12 hours ago        5.753 GBusryy/the-application   vx.xx.xx            5af809583b9c        3 days ago          5.743 GBusrzz/the-application   vx.xx.xx            eef00ce9b81f        10 days ago         5.747 GBusrAA/the-application   vx.xx.xx            422ba91c71bb        3 weeks ago         5.722 GBusrBB/the-application   v1.00.18            a877aec95006        3 months ago        5.589 GB
$ docker rmi usrxx/the-application:16112805 && docker rmi 011fd5bf45a2$ docker rmi usryy/the-application:vx.xx.xx && docker rmi 5af809583b9c$ docker rmi usrzz/the-application:vx.xx.xx eef00ce9b81f$ docker rmi usrAA/the-application:vx.xx.xx 422ba91c71bb$ docker rmi usrBB/the-application:v1.00.18 a877aec95006

例如,脚本删除任何超过2周的内容。

IMAGESINFO=$(docker images --no-trunc --format '\{\{.ID}} \{\{.Repository}} \{\{.Tag}} \{\{.CreatedSince}}' |grep -E " (weeks|months|years)")TAGS=$(echo "$IMAGESINFO" | awk '{ print $2 ":" $3 }' )IDS=$(echo "$IMAGESINFO" | awk '{ print $1 }' )echo remove old images TAGS=$TAGS IDS=$IDSfor t in $TAGS; do docker rmi $t; donefor i in $IDS; do docker rmi $i; done

几周前拆下旧容器。

docker rm $(docker ps -a | grep "weeks" | awk '{ print $1; }')

删除几周前的旧图像。请小心。这将删除几周前创建但新图像可能正在使用的基本图像。

docker rmi $(docker images | grep 'weeks' | awk '{ print $3; }')

假设您有docker 1.13或更高版本,您可以使用prune命令。对于您的问题,特别是删除旧图像,您想要第一个。

# Remove unused imagesdocker image prune
# Remove stopped containers.docker container prune
# Remove unused volumesdocker volume prune
# Remove unused networksdocker network prune
# Command to run all prunes:docker system prune

我建议没有习惯使用docker system prune命令。我认为用户会不小心删除他们不想删除的东西。就个人而言,我将主要使用docker image prunedocker container prune命令。

到目前为止(Docker版本1.12),我们使用以下命令删除所有正在运行的容器。此外,如果我们想删除卷,我们可以在以下命令中使用其相应的标签-v手动执行此操作。

删除所有已退出的容器

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

删除所有已停止的容器

docker rm $(docker ps -a -q)

删除所有正在运行和停止的容器

docker stop $(docker ps -a -q)docker rm $(docker ps -a -q)

删除所有容器,没有任何标准

docker container rm $(docker container ps -aq)

但是,在1.13及以上版本中,为了完成系统和清理,我们可以直接使用以下命令:

docker system prune

所有未使用的容器、图像、网络和卷都将被删除。我们还可以使用以下命令清理各个组件:

docker container prunedocker image prunedocker network prunedocker volume prune

我正在使用这个命令:

export BEFORE_DATETIME=$(date --date='10 weeks ago' +"%Y-%m-%dT%H:%M:%S.%NZ")docker images -q | while read IMAGE_ID; doexport IMAGE_CTIME=$(docker inspect --format='\{\{.Created}}' --type=image ${IMAGE_ID})if [[ "${BEFORE_DATETIME}" > "${IMAGE_CTIME}" ]]; thenecho "Removing ${IMAGE_ID}, ${BEFORE_DATETIME} is earlier then ${IMAGE_CTIME}"docker rmi -f ${IMAGE_ID};fi;done

这将删除创建时间大于10周前的所有图像。

如果您希望自动/定期清理退出的容器并删除正在运行的容器未使用的映像和卷,您可以下载映像meltwater/docker-cleanup

只需运行:

docker run -d -v /var/run/docker.sock:/var/run/docker.sock:rw  -v /var/lib/docker:/var/lib/docker:rw --restart=unless-stopped meltwater/docker-cleanup:latest

默认情况下,它每30分钟运行一次。但是,您可以使用此标志(DELAY_TIME=1800选项)设置延迟时间。

更多详情:https://github.com/meltwater/docker-cleanup/blob/master/README.md

docker system prune -a

(系统会要求您确认命令。如果您知道自己在做什么,请使用-f强制运行。)

其他答案都很棒,具体来说:

docker system prune # doesn't clean out old imagesdocker system prune --all # cleans out too much

但是我需要两个命令中间的一些东西,所以filter选项是我需要的:

docker image prune --all --filter "until=4320h" # delete images older than 6 months ago; 4320h = 24 hour/day * 30 days/month * 6 months

希望有帮助:)

参考:https://docs.docker.com/config/pruning/#prune-images

有麻雀插件docker-删除-悬挂-图像,您可以使用它来清理停止的容器和未使用的(悬空)图像:

$ sparrow plg run docker-remove-dangling-images

它适用于Linux和Windows OS。

同时修剪所有图像和卷
docker system prune -af --volumes

docker rm $(docker ps -faq)docker rmi $(docker ps -faq)

-f部队

-a所有

-q在模式

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

运行docker rmi -f <Image>

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

根据doc,以下命令将删除超过48小时的图像。

$ docker image prune --all --filter until=48h

如果您自己构建这些修剪后的图像(从其他一些较旧的基本图像),请注意上面基于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 obsolescencemy_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有一些命令可以帮助我们消除悬空图像。在旧版本的Docker中(今天仍然有效),您可以通过运行docker rmi -f $(docker images -f "dangling=true" -q) 自行删除悬空图像。

我通常做docker rm -f $(docker ps -a -q)docker system prune来清除所有悬挂的容器。

下面的命令将有助于从本地存储库中删除所有未使用的和旧的图像==>docker系统修剪--all

查看docker系统修剪的官方参考

docker system prune将删除:

  • 所有停止的容器
  • 未被至少一个容器使用的所有网络
  • 所有悬挂的图像
  • 所有构建缓存

docker system prune -a将执行相同的操作,但除了删除所有悬空图像外,它还将更广泛地删除:

  • 所有图像至少有一个容器与它们相关联

什么是悬挂图像?

Docker镜像由多层组成,当从Dockerfile生成整个容器镜像时,这些层被包裹在父“容器层”中。悬空镜像是与任何其他标记镜像没有关系的层,因此在构建的任何新容器中永远没有任何用处。它们不再有目的并消耗磁盘空间。

例如,可以通过以下过程创建悬挂图像:

从Dockerfile构建命名图像my-image,无需指定任何标记:

FROM ubuntu:latestCMD ["echo", "Hello World"]
docker build -t my-image
docker images
REPOSITORY   TAG       IMAGE IDmy-image     latest    7ed6e7202eca   <--- created, not danglingubuntu       latest    825d55fb6340

更新Dockerfile:

FROM ubuntu:latestCMD ["echo", "Hello, World!"]

重建图像重新使用以前的名称,不指定任何标签:

docker build -t my-image
docker images
REPOSITORY   TAG       IMAGE IDmy-image     latest    da6e74196f66   <--- replacement layer<none>       <none>    7ed6e7202eca   <--- previous layer, now danglingubuntu       latest    825d55fb6340

构建创建了一个新的my-image层。正如我们所看到的,最初创建的层仍然存在,但它的名称和标签设置为<none>:<none>。这一层永远不可能与任何docker容器层相关联,这意味着它是“悬空的”

没有至少一个容器关联的图像是什么?

未使用的映像意味着它尚未在容器中分配或使用。例如,docker ps -a将列出所有正在运行和停止的容器。任何这些容器使用的任何映像都是“已使用的映像”。

当运行docker系统prune-a时,它将删除未使用的和悬空的图像。任何与至少一个容器关联的图像都不会受到影响。