182

I'd like to find out if a Docker image with a specific tag exists locally. I'm fine by using a bash script if the Docker client cannot do this natively.

Just to provide some hints for a potential bash script the result of running the docker images command returns the following:

REPOSITORY                               TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
rabbitmq                                 latest              e8e654c05c91        5 weeks ago         143.5 MB
busybox                                  latest              8c2e06607696        6 weeks ago         2.433 MB
rabbitmq                                 3.4.4               a4fbaad9f996        11 weeks ago        131.5 MB
Johan
  • 37,479
  • 32
  • 149
  • 237

13 Answers13

249

I usually test the result of docker images -q (as in this script):

if [[ "$(docker images -q myimage:mytag 2> /dev/null)" == "" ]]; then
  # do something
fi

On Powershell (comment from Garret Wilson):

if (!(docker images -q myimage:mytag 2> $null)) { 
  # do something
}

But since docker images only takes REPOSITORY as parameter, you would need to grep on tag, without using -q.

docker images takes tags now (docker 1.8+) [REPOSITORY[:TAG]]

The other approach mentioned below is to use docker inspect.
But with docker 17+, the syntax for images is: docker image inspect (on an non-existent image, the exit status will be non-0)

As noted by iTayb in the comments:

  • The docker images -q method can get really slow on a machine with lots of images. It takes 44s to run on a 6,500 images machine.
  • The docker image inspect returns immediately.

As noted in the comments by Henry Blyth:

If you use docker image inspect my_image:my_tag, and you want to ignore the output, you can add --format="ignore me" and it will print that literally.

You can also redirect stdout by adding >/dev/null but, if you can't do that in your script, then the format option works cleanly.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    Hmm not sure if this works for tags? When I do "docker images -q rabbitmq" it returns "e8e654c05c91 and a4fbaad9f996" but if I do "docker images -q rabbitmq:3.4.4" nothing is returned even though the tag exist. – Johan May 30 '15 at 12:00
  • @Johan Even though the tag exists locally? – VonC May 30 '15 at 12:01
  • @Johan I just double-checked, and the docker images parameter indeed only takes the repo, not the tag. I have edited the answer to propose an alternative solution. – VonC May 30 '15 at 12:20
  • 2
    Thanks that seem to work. But perhaps you should edit your answer and remove ":mytag" from "myimage:mytag" before I accept it? – Johan May 30 '15 at 12:29
  • for the newbs: what is the different between an image (myimage) and a tag (mytag)? why myimage:mytag instead of just mytag? – Alexander Mills Dec 01 '16 at 09:45
  • @AlexanderMills Because a tag is not unique: it references a version of an image. – VonC Dec 01 '16 at 09:49
  • 1
    Warning: the `docker images -q` method can get really slow on a machine with lots of images. It takes 44s to run on a 6,500 images machine. The `docker image inspect` returns immediately. – iTayb Apr 21 '20 at 14:55
  • @iTayb Good point. I have included your comment in the answer for more visibility. – VonC Apr 21 '20 at 16:32
  • 1
    If you use `docker image inspect my_image:my_tag` and you want to ignore the output, you can add `--format="ignore me"` and it will print that literally. You can also redirect stdout by adding `>/dev/null` but if you can't do that in your script, then the format option works cleanly =) – Henry Blyth Aug 27 '21 at 14:56
  • 1
    @HenryBlyth Thank you for this feedback. I have included your comment in the answer for more visibility. – VonC Aug 27 '21 at 15:21
  • With some experimentation I've managed to get it to work on PowerShell, looking something like this: `if (!(docker images -q myimage:mytag 2> $null)) { … }` – Garret Wilson Mar 06 '23 at 22:20
  • @GarretWilson Nice! I have included your comment in the answer for more visibility. – VonC Mar 06 '23 at 23:23
  • @VonC Glad it was useful. You might consider spreading out the block `{ … }` to separate lines to be consistent with your other example, and remove the `…` and even add a comment in the block. I only listed it that way because I couldn't manage to enter multiple lines in the comment. – Garret Wilson Mar 07 '23 at 14:43
  • @GarretWilson Good point. I have edited the answer accordingly. I mentioned multi-line comments [back in 2009](https://meta.stackexchange.com/q/197/6309). – VonC Mar 07 '23 at 22:25
65

Try docker inspect, for example:

$ docker inspect --type=image treeder/hello.rb:nada
Error: No such image: treeder/hello.rb:nada
[]

But now with an image that exists, you'll get a bunch of information, eg:

$ docker inspect --type=image treeder/hello.rb:latest
[
{
    "Id": "85c5116a2835521de2c52f10ab5dda0ff002a4a12aa476c141aace9bc67f43ad",
    "Parent": "ecf63f5eb5e89e5974875da3998d72abc0d3d0e4ae2354887fffba037b356ad5",
    "Comment": "",
    "Created": "2015-09-23T22:06:38.86684783Z",
    ...
}
]

And it's in a nice json format.

thesamet
  • 6,382
  • 2
  • 31
  • 42
Travis Reeder
  • 38,611
  • 12
  • 87
  • 87
42

tldr:

docker image inspect myimage:mytag

By way of demonstration...

success, found image:

$ docker image pull busybox:latest
latest: Pulling from library/busybox
Digest: sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f
Status: Image is up to date for busybox:latest

$ docker image inspect busybox:latest >/dev/null 2>&1 && echo yes || echo no
yes

failure, missing image:

$ docker image rm busybox:latest
Untagged: busybox:latest
Untagged: busybox@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f

$ docker image inspect busybox:latest >/dev/null 2>&1 && echo yes || echo no
no

Reference:

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

rubicks
  • 4,912
  • 1
  • 30
  • 41
  • this was straightforward, quick and compatible up to the future. I'll stick to this solution. – MarAvFe Mar 04 '20 at 23:57
  • To be more specific, specify `--type image` for images, or `--type container` for existing containers – smac89 May 01 '21 at 18:23
  • @smac89, I'm not familiar with that option. ``` $ docker --version Docker version 20.10.6, build 370c289 $ docker image inspect --help Usage: docker image inspect [OPTIONS] IMAGE [IMAGE...] Display detailed information on one or more images Options: -f, --format string Format the output using the given Go template ``` – rubicks May 01 '21 at 22:16
  • Oh whoops, I was doing `docker inspect`, not `docker image inspect`. – smac89 May 02 '21 at 02:31
28

You can use like the following:

[ -n "$(docker images -q someimage:sometag)" ] || echo "does not exist"

Or:

[ -z "$(docker images -q someimage:sometag)" ] || echo "already exists"
Aidin
  • 25,146
  • 8
  • 76
  • 67
Luís Bianchin
  • 2,327
  • 1
  • 28
  • 36
  • 9
    Does not work, on macOS at least, the return value is always 0. – Gabor Csardi Nov 30 '16 at 20:33
  • 2
    The code is correct and works on linux. Only thing I'd add is quotes to the subshell command – Draiken Jul 19 '17 at 21:29
  • 2
    @GaborCsardi This one works on MacOS: `[[ -z "$(docker images -q someimage:sometag)" ]] || echo "exists"` as well as `[[ -n "$(docker images -q someimage:sometag)" ]] || echo "doesn't exist"`. Edited answer. Should work fine now. Gabor, can you please confirm? – Aidin Apr 28 '21 at 19:11
3

With the help of Vonc's answer above I created the following bash script named check.sh:

#!/bin/bash
image_and_tag="$1"
image_and_tag_array=(${image_and_tag//:/ })
if [[ "$(docker images ${image_and_tag_array[0]} | grep ${image_and_tag_array[1]} 2> /dev/null)" != "" ]]; then
  echo "exists"
else
  echo "doesn't exist"
fi

Using it for an existing image and tag will print exists, for example:

./check.sh rabbitmq:3.4.4

Using it for a non-existing image and tag will print doesn't exist, for example:

./check.sh rabbitmq:3.4.3
Community
  • 1
  • 1
Johan
  • 37,479
  • 32
  • 149
  • 237
3

In case you are trying to search for a docker image from a docker registry, I guess the easiest way to check if a docker image is present is by using the Docker V2 REST API Tags list service

Example:-

curl $CURLOPTS -H "Authorization: Bearer $token" "https://hub.docker.com:4443/v2/your-repo-name/tags/list"

if the above result returns 200Ok with a list of image tags, then we know that image exists

{"name":"your-repo-name","tags":["1.0.0.1533677221","1.0.0.1533740305","1.0.0.1535659921","1.0.0.1535665433","latest"]}

else if you see something like

{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known to registry","detail":{"name":"your-repo-name"}}]} 

then you know for sure that image doesn't exist.

Abhishek J
  • 101
  • 7
2

Using test

if test ! -z "$(docker images -q <name:tag>)"; then
  echo "Exist"
fi

or in one line

test ! -z "$(docker images -q <name:tag>)" &&  echo exist
Alex Montoya
  • 4,697
  • 1
  • 30
  • 31
2

In bash script I do this to check if image exists by tag :

IMAGE_NAME="mysql:5.6"

if docker image ls -a "$IMAGE_NAME" | grep -Fq "$IMAGE_NAME" 1>/dev/null; then
echo "could found image $IMAGE_NAME..."
fi

Example script above checks if mysql image with 5.6 tag exists. If you want just check if any mysql image exists without specific version then just pass repository name without tag as this :

IMAGE_NAME="mysql"
Namig Hajiyev
  • 1,117
  • 15
  • 16
1

Inspired by @rubicks's response above.

To check if the image exists already

image_name_tag="alpine:3.13.3"

docker image inspect ${image_name_tag} > /dev/null
echo $?

Pull if image does not exist

docker image inspect ${image_name_tag} > /dev/null || docker  pull ${image_name_tag}

Demo execution

# image_name_tag="alpine:3.13.3"
# 
# docker image inspect ${image_name_tag} > /dev/null
echo $?
Error: No such image: alpine:3.13.3
# echo $?
1
# docker image inspect ${image_name_tag} > /dev/null || docker  pull ${image_name_tag}
Error: No such image: alpine:3.13.3
3.13.3: Pulling from library/alpine
9aae54b2144e: Pull complete 
Digest: sha256:826f70e0ac33e99a72cf20fb0571245a8fee52d68cb26d8bc58e53bfa65dcdfa
Status: Downloaded newer image for alpine:3.13.3
docker.io/library/alpine:3.13.3
# docker image inspect ${image_name_tag} > /dev/null || docker  pull ${image_name_tag}
$ 
Rakesh Gupta
  • 3,507
  • 3
  • 18
  • 24
0

Just a bit from me to very good readers:

Build

#!/bin/bash -e
docker build -t smpp-gateway smpp
(if  [ $(docker ps -a | grep smpp-gateway | cut -d " " -f1) ]; then \
  echo $(docker rm -f smpp-gateway); \
else \
  echo OK; \
fi;);
docker run --restart always -d --network="host" --name smpp-gateway smpp-gateway:latest

Watch

docker logs --tail 50 --follow --timestamps smpp-gateway

Run

sudo docker exec -it \
$(sudo docker ps | grep "smpp-gateway:latest" | cut -d " " -f1) \
/bin/bash
Alan Turing
  • 2,482
  • 17
  • 20
0

for specific tag name

$ docker images  --filter reference='<REPOSITORY>:TAG'

for "like clause" tagname:my_image_tag --> start my_ima*

$ docker images  --filter reference='<REPOSITORY>:my_ima*'

if you want to someting "the image" for example delete all images tag started "my_ima" try this

docker rmi -f $(docker images -q  --filter reference='myreponame:my_ima*')
raVen
  • 29
  • 4
  • If the image doesn't exist, the exit code is still 0. As such, it's not relevant to be used in a script, only for humans (who can use the more universal docker images | grep too) – Dereckson Sep 28 '20 at 23:22
0

I think this functionality should be implemented inside the docker build command (using a flag?), so that it avoids a lot of code duplication.

I used the same condition as the accepted answer inside a wrapper function called docker_build so that it does the necessary checks before calling the original docker build command.

# Usage: docker_build <...> (instead of docker build)

docker_build()
{
    local arguments=("$@")
    local index
    for (( index=0; index<$#; index++ )); do
        case ${arguments[index]} in
            --tag)
                local tag=${arguments[index+1]}
                if [[ ! -z $(docker images -q "${tag}" 2> /dev/null) ]]; then
                    echo "Image ${tag} already exists."
                    return
                fi
                ;;
        esac
    done
    command docker build "$@"
}

Disclaimer: This is not ready for production because it works only with space-separated arguments in long format i.e --tag hello-world:latest. Also, this just modifies the docker build command only, all other commands remain same. If anyone has improvements, please let me know.

I felt like sharing this snippet because the idea of wrapping-standard-commands-in-bash-functions, to avoid code repetition, seemed more elegant and scalable than writing wrapper statements.

Nishant
  • 20,354
  • 18
  • 69
  • 101
0

I like this because it is concise and has the proper semantics. If the image exists it is true what could be easier?

if [ $(docker image ls ${build_env} --format="true") ] ; 
then
 echo "does exist"
fi