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

Qua*_*ong 697 docker docker-image

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

另外,我还想删除几个月前拉出的图片,这些都是正确的TAG.

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

Von*_*onC 1331

2016年9月更新:Docker 1.13:PR 26108commit 86de7c0引入了一些新命令,以帮助显示docker守护程序数据在磁盘上占用多少空间,并允许轻松清理"不需要的"多余空间.

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

你还有:

对于未使用的图像,请使用docker image prune -a(用于删除悬空未图像).
警告:' unused '表示"未被任何容器引用的图像":使用前请小心-a.

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

结合docker xxx prune--filter选项可以限制修剪的好方法(泊坞窗SDK API 1.28最低,所以搬运工17.04+)

目前支持的过滤器是:

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

有关示例,请参见" 修剪图像 ".


原始答案(2016年9月)

我经常这样做:

docker rmi $(docker images --filter "dangling=true" -q --no-trunc)
Run Code Online (Sandbox Code Playgroud)

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

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

这样,删除了标记图像不再引用的任何中间图像.

首先退出的进程(容器)做同样的事情

alias drmae='docker rm $(docker ps -qa --no-trunc --filter "status=exited")'
Run Code Online (Sandbox Code Playgroud)

正如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
}
Run Code Online (Sandbox Code Playgroud)

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


一个简单的Docker容器和图像垃圾收集脚本.

  • 退出一个多小时前的容器将被删除.
  • 之后不属于任何剩余容器的图像将被删除.

  • 有关于"悬空=真"的真实含义的文件吗? (22认同)
  • @herm首先,`docker system prune`删除的不仅仅是图像.确保使用`docker image prune`代替.用'-a`非常小心**:`docker system prune -a`可能会产生毁灭性的影响(同时删除音量).最后,是的,`-a`删除未使用的图像,我将编辑答案. (3认同)
  • `dcleanup`太棒了! (2认同)
  • @stom:“未使用”表示“没有任何容器引用的图像,但悬空意味着根本没有标记(只是一个ID)。 (2认同)

rub*_*cks 117

更新第二个(2017-07-08):

使用更新的版本(再次)参考VonC system prune.不耐烦的人可以跳过提示-f, --force选项:

docker system prune -f
Run Code Online (Sandbox Code Playgroud)

不耐烦和鲁莽可以另外删除"未使用的图像而不仅仅是悬空图像" -a, --all选项:

docker system prune -af
Run Code Online (Sandbox Code Playgroud)

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 '
Run Code Online (Sandbox Code Playgroud)

老答案:

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

$ docker ps --no-trunc -aqf "status=exited" | xargs docker rm
Run Code Online (Sandbox Code Playgroud)

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

$ docker images --no-trunc -aqf "dangling=true" | xargs docker rmi
Run Code Online (Sandbox Code Playgroud)

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

$ docker volume ls -qf "dangling=true" | xargs docker volume rm
Run Code Online (Sandbox Code Playgroud)

在这里,它们是一个方便的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'
Run Code Online (Sandbox Code Playgroud)

参考文献:

  • 我会谨慎处理卷清理.自动创建的容器卷和当前未使用的命名卷都与dangling = true一起列出. (3认同)
  • 是的,但不幸的是,它没有使用简单的标志将命名卷与匿名容器卷分开.我一直在使用的命令是`docker volume ls -qf dangling = true | egrep'^ [a-z0-9] {64} $'| xargs --no-run-if-empty docker volume rm`只要您从未使用类似guid的内容命名卷,它就会起作用.我可以调整这个以获得新的过滤器语法. (2认同)

Wer*_*ght 53

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

$ docker images --no-trunc --format '{{.ID}} {{.CreatedSince}}' \
    | grep ' months' | awk '{ print $1 }' \
    | xargs --no-run-if-empty docker rmi
Run Code Online (Sandbox Code Playgroud)

请注意,它将无法删除容器使用的图像,在存储库中引用,具有依赖子图像......这可能是您想要的.否则只需添加-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
Run Code Online (Sandbox Code Playgroud)

  • +1用于删除旧docker镜像的命令.它有点hacky,但解决方案是原始的,完美的工作:) (2认同)
  • 很好,但是我认为这只会删除至少** 4个月**的docker镜像。“ .CreatedSince”使用星期作为输出中的时间单位,即使在使用了几周的图像上也是如此,例如“ 12周”。 (2认同)
  • 这对我有用,很好很简单:`docker images | grep '月' | awk '{ 打印 $3 }' | xargs --no-run-if-empty docker rmi -f` (2认同)

Shr*_*ash 27

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

$ docker image prune --all --filter until=48h
Run Code Online (Sandbox Code Playgroud)

  • 使用过滤器还可以列出指定版本之前的每个版本:`docker image ls --all --filter reference=monolito --filter before=monolito:0.1.8`,然后应用 rmi 命令进行删除。`docker rmi $(docker image ls -q --all --filter 参考=monolito --filter before=monolito:0.1.8)` (2认同)

A L*_*A L 24

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

docker system prune # doesn't clean out old images
docker system prune --all # cleans out too much
Run Code Online (Sandbox Code Playgroud)

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

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

希望有帮助:)

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

  • 非常被低估的答案!能够根据截止日期进行修剪非常有用。 (6认同)
  • 我还使用这种语法来使其更具可读性 `--filter "until=$((30*24))h"` 或者在这种情况下像 `--filter "until=$((24*30*6))小时”` (3认同)

Pro*_*ter 23

假设你有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
Run Code Online (Sandbox Code Playgroud)

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

  • 你不想修剪未使用的网络吗?比如,如果所有容器都停止了,我删除了那些网络,如果我启动它们,它们将如何工作.网络是否与docker一起创建? (3认同)

Mah*_*alt 13

这对我有用:

docker rmi $(docker images | grep "^<none>" | awk "{print $3}")
Run Code Online (Sandbox Code Playgroud)


moh*_*08p 13

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

删除所有已退出的容器

docker rm $(docker ps -q -f status=exited)
Run Code Online (Sandbox Code Playgroud)

删除所有已停止的容器

docker rm $(docker ps -a -q)
Run Code Online (Sandbox Code Playgroud)

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

docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
Run Code Online (Sandbox Code Playgroud)

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

docker container rm $(docker container ps -aq)
Run Code Online (Sandbox Code Playgroud)

但是,在1.13及更高版本中,对于完整的系统和清理,我们可以直接使用以下命令:

docker system prune
Run Code Online (Sandbox Code Playgroud)

所有未使用的容器,图像,网络和卷都将被删除.我们也可以使用以下清理单个组件的命令来执行此操作:

docker container prune
docker image prune
docker network prune
docker volume prune
Run Code Online (Sandbox Code Playgroud)


Ell*_*eal 9

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

#!/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 ':' '$2{print $1":"$2}!$2{print $1":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
Run Code Online (Sandbox Code Playgroud)


vis*_*dhe 8

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

#!/bin/bash -x
## Removing stopped container
docker 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.
Run Code Online (Sandbox Code Playgroud)

原始剧本

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

通常,Docker会保留与图像构建和图层相关的所有临时文件

在/ var/lib中/泊坞窗

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

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

这样,即使Docker镜像占用空间,它也不会影响您的系统,因为它将使用其他一些安装位置.

原帖:在本地磁盘上管理Docker镜像


spe*_*007 6

如果您想删除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
Run Code Online (Sandbox Code Playgroud)


Yon*_*ron 6

我正在使用以下命令:

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
Run Code Online (Sandbox Code Playgroud)

这将删除所有创建时间超过10周的图像。


Zay*_*try 5

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