docker - 删除所有没有容器或子镜像的 Docker 镜像,即使它们被标记

标签 docker

我想清理当前容器未直接或间接使用的所有 Docker 镜像。 Docker 提供了 docker image prune命令,但我无法让它完全删除我想要的东西。如果我在没有 -a 的情况下使用该命令,它删除的太少:它会留下所有标记的图像,即使没有容器使用它们。如果我将该命令与 -a 一起使用,它删除了太多:它删除了未删除的图像的父图像。这是一个解释问题的表格:

Used by container | Has child image | Has tag | Removed without -a | Removed with -a | I want to remove
Yes               | Yes/No          | Yes/No  | No                 | No              | No
No                | Yes             | Yes/No  | No                 | Yes             | No
No                | No              | Yes     | No                 | Yes             | Yes
No                | No              | No      | Yes                | Yes             | Yes

此命令是否有其他标志(例如带有 --filter 的标志)或其他一些命令或命令序列,可以让我删除我想要删除的内容?

编辑 :David Maze在评论中指出我所指的图像只是未标记,并未完全删除。鉴于此,这里是问题的更新措辞:我如何制作 docker image prune -a不取消标记它实际上不会删除的图像?

最佳答案

我经常想同样的事情,所以我想出了这个解决方案:

# create unique array of image ids (including all descendants) used by running containers
get_active_image_history()
{
    for image_name in $(docker ps --format={{.Image}})
    do
        docker history -q $image_name
    done | sort -u
}

# iterate over each image id in your system, and output the ids that should be deleted
# conceptually similar to an intersection of two arrays
get_unused_image_ids()
{
    image_history=$(get_active_image_history)
    for image_id in $(docker image ls -q)
    do
        if [[ ! "${image_history[@]}" =~ "${image_id}" ]]; then
            echo "$image_id"
        fi
    done  | sort -u
}

docker_clean()
{
    image_ids=$(get_unused_image_ids)
    if [ -z "$image_ids" ]; then
        >&2 echo "Error: no unused images found"
        return 1
    fi

    if [[ "$1" = "-y" ]]; then
        echo y | docker container prune > /dev/null
        docker image rm $(get_unused_image_ids)
        return 0
    fi

    echo -e "Warning! this will remove all stopped containers, and the following images:\n"
    image_ids=$(get_unused_image_ids)
    echo "REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE"
    docker image ls | grep "$image_ids"
    echo
    read -p "Continue (y/n)?" cont
    if [ "$cont" = "y" ]; then
        echo y | docker container prune > /dev/null
        docker image rm $image_ids
    else
        echo "aborting..."
    fi
}
不是很优雅,但它在开发中运行良好。您可以通过 -y标志使警告提示静音。
我遇到过几种情况,提示错误地显示了当前正在使用的图像,并试图将其删除,但随后被捕获
docker 守护进程会导致类似以下的误导性噪音:
Error response from daemon: conflict: unable to delete <image id> (must be forced) -
image is being used by stopped container <container id>
在所有情况下,只删除了正确的图像,但这可能因您的系统而异。青年会
TLDR;不安全生产

关于docker - 删除所有没有容器或子镜像的 Docker 镜像,即使它们被标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52882184/

相关文章:

ruby-on-rails - Docker:在$ PATH中找不到Rails可执行文件

docker - pika.exceptions.ConnectionClosed:与172.18.0.3:5672的连接失败:[Errno 111]连接被拒绝

web-applications - docker : How To Dockerize And Deploy multiple instances of a LAMP Application

linux - 如何解决 "docker: Error response from daemon: OCI runtime create failed: unable to retrieve OCI runtime error"

ruby-on-rails - 套接字错误 : Failed to open TCP connection to rubygmes. 组织:443

docker - 如何从Docker容器从主机运行病毒扫描程序脚本

windows - 如何使用 docker compose 卷挂载 windows 文件夹?

java - 允许主机应用程序访问安装在 Docker 容器中的 Java SDK

docker - 找出 docker-compose 传递给容器的环境变量的值

挂载卷时 Docker 的行为