如何删除旧的和未使用的 Docker 图片

How to remove old and unused Docker images

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

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

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

提取的图像

(原回答见下)


2016 年 9 月更新:Docker 1.13:PR 26108 and commit 86de7c0 引入了一些新命令以帮助可视化 space docker 守护程序数据在磁盘上的占用量并允许轻松清理“不需要的”多余部分。

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

您还有:

对于未使用的图像,使用docker image prune -a(用于删除悬挂的未使用的图像)。
警告:'unused' 的意思是“镜像没有被任何容器引用”:使用 -a.

之前要小心

A L's 中所示,docker system prune --all 将删除所有 未使用的 图像,而不仅仅是悬挂的图像......这可能有点太多了。

结合 docker xxx prune--filter option can be a great way to limit the pruning (docker SDK API 1.28 minimum, so docker 17.04+)

The currently supported filters are:

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

示例请参见“Prune images”。

原始答案(2016 年 9 月)

我经常这样做:

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

我有一个[用于删除那些 dangling images: drmi]13

的别名

The dangling=true filter finds unused images

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

我先 exited processes (containers)

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

作为haridsv points out :

Technically, you should first clean up containers before cleaning up images, as this will catch more dangling images and less errors.


Jess Frazelle (jfrazelle) has the bashrc function:

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:


A simple Docker container and image garbage collection script.

  • Containers that exited more than an hour ago are removed.
  • Images that don't belong to any remaining container after that are removed.

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

#!/bin/bash

imgs=$(docker images | awk '/<none>/ { print  }')
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

如果你想删除 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/

更新

参考使用最近添加的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

如果您对不可撤销的数据丢失[=74]采取了极度谨慎 =],然后您可以删除未使用的(悬空的)卷(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  }' \
    | 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  }' | 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 }")

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

#!/bin/bash

# Remove all the dangling images
DANGLING_IMAGES=$(docker images -qf "dangling=true")
if [[ -n $DANGLING_IMAGES ]]; then
    docker rmi "$DANGLING_IMAGES"
fi

# Get all the images currently in use
USED_IMAGES=($( \
    docker ps -a --format '{{.Image}}' | \
    sort -u | \
    uniq | \
    awk -F ':' '{print ":"}!{print ":latest"}' \
))

# Get all the images currently available
ALL_IMAGES=($( \
    docker images --format '{{.Repository}}:{{.Tag}}' | \
    sort -u \
))

# Remove the unused images
for i in "${ALL_IMAGES[@]}"; do
    UNUSED=true
    for j in "${USED_IMAGES[@]}"; do
        if [[ "$i" == "$j" ]]; then
            UNUSED=false
        fi
    done
    if [[ "$UNUSED" == true ]]; then
        docker rmi "$i"
    fi
done

这是一个脚本,用于清理 Docker 图像并回收 space。

#!/bin/bash -x
## Removing stopped container
docker ps -a | grep Exited | awk '{print }' | 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 }' | xargs docker rm
#docker ps -a | grep Exited | grep "weeks ago" | awk '{print }' | 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 }')

## Removing weeks old images

docker images | grep "weeks ago" | awk '{print }' | xargs docker rmi

## Similarly you can remove days, months old images too.

原剧本

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

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

/var/lib/docker

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

您可以安装更大的磁盘 space 并将 /var/lib/docker 的内容移动到新的安装位置并制作一个符号 link.

这样,即使 Docker 个图像占用 space,它也不会影响您的系统,因为它会使用其他安装位置。

原文post: Manage Docker images on local disk

要删除没有容器 运行 的标记图像,您将不得不使用一个小脚本:

#!/bin/bash

# remove not running containers
docker rm $(docker ps -f "status=exited" -q)

declare -A used_images

# collect images which has running container
for image in $(docker ps | awk 'NR>1 {print ;}'); do
    id=$(docker inspect --format="{{.Id}}" $image);
    used_images[$id]=$image;
done

# loop over images, delete those without a container
for id in $(docker images --no-trunc -q); do
    if [ -z ${used_images[$id]} ]; then
        echo "images is NOT in use: $id"
        docker rmi $id
    else
        echo "images is in use:     ${used_images[$id]}"
    fi
done

偶尔我 运行 遇到 Docker 将分配并继续使用磁盘 space 的问题,即使 space 未分配给任何特定图像或现有容器。我意外产生这个问题的最新方法是在 RHEL 7.1 中使用“docker-engine”centos build 而不是“docker”。似乎发生的情况是有时容器清理没有成功完成,然后 space 永远不会被重用。当我分配为 / 的 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

此时我不再有磁盘已满的错误,但我仍然在浪费大量 space。接下来的步骤就是解决这个问题。

  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. 启动您需要的任何持久容器运行ning。

这使我的磁盘使用量从 docker 的 67 GB 下降到 docker 的 6 GB。

我不推荐日常使用。但它对 运行 很有用,因为它看起来像 docker 丢失了已用磁盘的踪迹 space 对软件错误或意外重新启动。

如何删除标记的图像

  1. docker 首先 rmi 标签

  2. docker rmi 图像。

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

(2016 年 11 月有效,Docker 版本 1.12.2)

例如

$ docker images 
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
usrxx/the-application   16112805            011fd5bf45a2        12 hours ago        5.753 GB
usryy/the-application   vx.xx.xx            5af809583b9c        3 days ago          5.743 GB
usrzz/the-application   vx.xx.xx            eef00ce9b81f        10 days ago         5.747 GB
usrAA/the-application   vx.xx.xx            422ba91c71bb        3 weeks ago         5.722 GB
usrBB/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  ":"  }' )
IDS=$(echo "$IMAGESINFO" | awk '{ print  }' )
echo remove old images TAGS=$TAGS IDS=$IDS
for t in $TAGS; do docker rmi $t; done
for i in $IDS; do docker rmi $i; done

删除几周前的旧容器。

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

删除几周前的旧图片。当心。这将删除几周前创建但您的新图像可能正在使用的基础图像。

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

假设您有 Docker 1.13 或更高版本,您可以使用 prune 命令。对于您专门针对删除旧图像的问题,您需要第一个。

# Remove unused images
docker image prune

# Remove stopped containers.
docker container prune

# Remove unused volumes
docker volume prune

# Remove unused networks
docker 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 prune
docker image prune
docker network prune
docker volume prune

我正在使用这个命令:

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

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

如果您希望 automatically/periodically 清理退出的容器并删除 运行ning 容器未使用的图像和卷​​,您可以下载图像 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 images
docker 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

有 sparrow 插件 docker-remove-dangling-images 可以用来清理停止的容器和未使用的(悬挂的)图像:

$ 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力

-全部

-q 模式

首先,运行 docker images 查看图像列表并将图像哈希 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 obsolescence
my_deleted_image_obsolete_tag_ids=$(docker images --filter="before=$monitored_image:$date_week_ago" | grep $my_deleted_image | awk '{print }')

# 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 来清除所有悬挂的容器。