Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove all Docker images without containers or child images, even if they're tagged

Tags:

docker

I want to clean up all of my Docker images that aren't being used, directly or indirectly, by my current containers. Docker provides the docker image prune command for this, but I can't get it to remove exactly what I want. If I use that command without -a, it removes too little: it leaves behind all tagged images, even if no container uses them. If I use that command with -a, it removes too much: it removes images that are parents of images that aren't being removed. Here's a table explaining the problem:

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

Is there some other flag for this command (such as something with --filter), or some other command or sequence of commands, that lets me remove just what I want to remove?

EDIT: David Maze points out in the comments that the images I'm referring to are merely being untagged, not removed entirely. Given that, here's an updated phrasing of the question: How can I make docker image prune -a not untag images that it's not actually going to remove?

like image 625
Joseph Sible-Reinstate Monica Avatar asked Oct 18 '18 20:10

Joseph Sible-Reinstate Monica


People also ask

How do I remove untagged docker images?

You can remove an image with docker rmi command, passing the name of the image you want to remove. This will remove the image. Sometimes when testing and developing, some images become dangling, which means untagged images. They can always be safely removed to free disk space.

How do I force delete all docker images?

Remove all images All the Docker images on a system can be listed by adding -a to the docker images command. Once you're sure you want to delete them all, you can add the -q flag to pass the image ID to docker rmi : List: docker images -a.


1 Answers

I often wondered the same thing, so I came up with this solution:

# 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
}

No very elegant, but it works well enough for use in development. You can pass a -y flag to silence the warning prompt.

There are several cases that I came across where the prompt incorrectly showed an image that was currently used, and attempted to remove it, but was then caught by the docker daemon which results in misleading noise similar to this:

Error response from daemon: conflict: unable to delete <image id> (must be forced) -
image is being used by stopped container <container id>

In all cases, only the correct images were removed, but this might vary depending on your system. YMMV

TLDR; not production safe

like image 53
Lord Elrond Avatar answered Oct 04 '22 19:10

Lord Elrond