如何检查本地是不是存在带有特定标签的 Docker 镜像?
Posted
技术标签:
【中文标题】如何检查本地是不是存在带有特定标签的 Docker 镜像?【英文标题】:How to check if a Docker image with a specific tag exist locally?如何检查本地是否存在带有特定标签的 Docker 镜像? 【发布时间】:2015-08-13 03:16:34 【问题描述】:我想知道本地是否存在带有特定标签的 Docker 映像。如果 Docker 客户端本身无法执行此操作,我可以使用 bash 脚本。
只是为潜在的 bash 脚本提供一些提示,运行 docker images
命令的结果返回以下内容:
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
【问题讨论】:
【参考方案1】:我通常测试docker images -q
的结果(如this script):
if [[ "$(docker images -q myimage:mytag 2> /dev/null)" == "" ]]; then
# do something
fi
但是由于。docker images
只接受REPOSITORY
作为参数,你需要在标签上grep,而不使用-q
docker images
现在接受标签(docker 1.8+)[REPOSITORY[:TAG]]
下面提到的另一种方法是使用docker inspect。
但是对于 docker 17+,图像的语法是:docker image inspect
(在不存在的图像上,exit status will be non-0)
正如iTayb 在the comments 中所指出的:
docker images -q
方法在具有大量图像的机器上会变得非常慢。在 6500 张图像的机器上运行需要 44 秒。
docker image inspect
立即返回。
Henry Blyth 在 cmets 中指出:
如果你使用
docker image inspect my_image:my_tag
,并且你想忽略输出,你可以添加--format="ignore me"
,它会直接打印出来。您也可以通过添加
>/dev/null
来重定向标准输出,但是,如果您不能在脚本中这样做,那么格式选项可以正常工作。
【讨论】:
嗯不确定这是否适用于标签?当我执行“docker images -q rabbitmq”时,它返回“e8e654c05c91 and a4fbaad9f996”,但如果我执行“docker images -q rabbitmq:3.4.4”,即使标签存在,也不会返回任何内容。 @Johan 即使标签存在于本地? @Johan 我只是仔细检查了一遍,docker images 参数确实只接受了 repo,而不是标签。我已编辑答案以提出替代解决方案。 谢谢,这似乎有效。但也许你应该编辑你的答案并在我接受之前从“myimage:mytag”中删除“:mytag”? @HenryBlyth 感谢您的反馈。我已将您的评论包含在答案中以提高知名度。【参考方案2】:试试docker inspect
,例如:
$ docker inspect --type=image treeder/hello.rb:nada
Error: No such image: treeder/hello.rb:nada
[]
但是现在有了一个存在的图像,你会得到一堆信息,例如:
$ docker inspect --type=image treeder/hello.rb:latest
[
"Id": "85c5116a2835521de2c52f10ab5dda0ff002a4a12aa476c141aace9bc67f43ad",
"Parent": "ecf63f5eb5e89e5974875da3998d72abc0d3d0e4ae2354887fffba037b356ad5",
"Comment": "",
"Created": "2015-09-23T22:06:38.86684783Z",
...
]
而且它是一个不错的 json 格式。
【讨论】:
这是最适合编写脚本的答案。 确实,images
和 ps
命令总是以 0 退出,inspect
很简单:docker inspect "$image_id:$image_tag" > /dev/null 2>&1 || echo "does not exist!"
docker inspect
很棒,因为在不存在图像时返回非零代码。
这也比docker images -q
快得多。
如果你想在你的脚本中禁止输出:if ! docker inspect <CONDITION> >> temp_docker-inspect.txt; then ...
【参考方案3】:
tldr:
docker image inspect myimage:mytag
通过演示的方式...
成功,找到图片:
$ 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
失败,图片丢失:
$ 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
参考:
https://docs.docker.com/engine/reference/commandline/image_inspect/
【讨论】:
这很简单,快速且兼容未来。我会坚持这个解决方案。 更具体地说,为图像指定--type image
,或为现有容器指定--type container
@smac89,我不熟悉那个选项。 ``` $ docker --version Docker version 20.10.6, build 370c289 $ docker image inspect --help 用法:docker image inspect [OPTIONS] IMAGE [IMAGE...] 显示一个或多个图像的详细信息 选项:-f , --format string 使用给定的 Go 模板格式化输出```
哦,哎呀,我在做docker inspect
,而不是docker image inspect
。【参考方案4】:
你可以像下面这样使用:
[ -n "$(docker images -q someimage:sometag)" ] || echo "does not exist"
或者:
[ -z "$(docker images -q someimage:sometag)" ] || echo "already exists"
【讨论】:
不起作用,至少在macOS上,返回值始终为0。 代码正确,适用于linux。我唯一要添加的是子shell命令的引号 @GaborCsardi 这个适用于 MacOS:[[ -z "$(docker images -q someimage:sometag)" ]] || echo "exists"
和 [[ -n "$(docker images -q someimage:sometag)" ]] || echo "doesn't exist"
。编辑答案。现在应该可以正常工作了。 Gabor,你能确认一下吗?【参考方案5】:
在上面Vonc's answer 的帮助下,我创建了以下名为check.sh
的bash 脚本:
#!/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
将其用于现有图像和标签将打印exists
,例如:
./check.sh rabbitmq:3.4.4
将它用于不存在的图像和标签将打印doesn't exist
,例如:
./check.sh rabbitmq:3.4.3
【讨论】:
【参考方案6】:如果您尝试从 docker 注册表中搜索 docker 映像,我想检查 docker 映像是否存在的最简单方法是使用 Docker V2 REST API Tags list service
例子:-
curl $CURLOPTS -H "Authorization: Bearer $token" "https://hub.docker.com:4443/v2/your-repo-name/tags/list"
如果上面的结果返回 200Ok 并带有图像标签列表,那么我们知道图像存在
"name":"your-repo-name","tags":["1.0.0.1533677221","1.0.0.1533740305","1.0.0.1535659921","1.0.0.1535665433","latest"]
如果你看到类似的东西
"errors":["code":"NAME_UNKNOWN","message":"repository name not known to registry","detail":"name":"your-repo-name"]
那么你肯定知道该图像不存在。
【讨论】:
【参考方案7】:使用test
if test ! -z "$(docker images -q <name:tag>)"; then
echo "Exist"
fi
或一行
test ! -z "$(docker images -q <name:tag>)" && echo exist
【讨论】:
【参考方案8】:在 bash 脚本中,我这样做是为了通过标签检查图像是否存在:
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
上面的示例脚本检查是否存在带有 5.6 标签的 mysql 映像。如果您只想检查是否存在任何没有特定版本的 mysql 映像,那么只需传递不带标签的存储库名称:
IMAGE_NAME="mysql"
【讨论】:
【参考方案9】:受上述@rubicks 回复的启发。
检查图像是否已经存在
image_name_tag="alpine:3.13.3"
docker image inspect $image_name_tag > /dev/null
echo $?
如果图片不存在则拉取
docker image inspect $image_name_tag > /dev/null || docker pull $image_name_tag
演示执行
# 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
$
【讨论】:
【参考方案10】:我只是给非常好的读者一点点:
构建
#!/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
观看
docker logs --tail 50 --follow --timestamps smpp-gateway
运行
sudo docker exec -it \
$(sudo docker ps | grep "smpp-gateway:latest" | cut -d " " -f1) \
/bin/bash
【讨论】:
【参考方案11】:对于特定的标签名称
$ docker images --filter reference='<REPOSITORY>:TAG'
for "like 子句" tagname:my_image_tag --> start my_ima*
$ docker images --filter reference='<REPOSITORY>:my_ima*'
如果你想要一些“图像”,例如删除所有图像标签开始“my_ima”试试这个
docker rmi -f $(docker images -q --filter reference='myreponame:my_ima*')
【讨论】:
如果镜像不存在,退出码依然为0。因此,它与在脚本中使用无关,仅对人类(谁可以使用更通用的docker镜像| grep 也是)【参考方案12】:我认为这个功能应该在docker build
命令中实现(使用标志?),这样可以避免大量的代码重复。
我在名为docker_build
的包装函数中使用了与accepted answer 相同的条件,以便在调用原始docker build
命令之前进行必要的检查。
# 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 "$@"
免责声明:这不适用于生产,因为它仅适用于长格式的空格分隔参数,即--tag hello-world:latest
。此外,这只是修改了docker build
命令,所有其他命令保持不变。如果有人有改进,请告诉我。
我之所以愿意分享这个 sn-p,是因为在 bash-functions 中包装标准命令以避免代码重复的想法似乎比编写包装语句更优雅和可扩展。
【讨论】:
【参考方案13】:我喜欢这个,因为它简洁并且具有正确的语义。如果图像存在,那是真的,还有什么比这更容易的呢?
if [ $(docker image ls $build_env --format="true") ] ;
then
echo "does exist"
fi
【讨论】:
以上是关于如何检查本地是不是存在带有特定标签的 Docker 镜像?的主要内容,如果未能解决你的问题,请参考以下文章
JGit:我可以在不检查的情况下找出某个特定标签是不是存在于 Git 存储库中吗?
如何通过带有本地容器注册表的 Docker 标签检索 SCDF 应用程序元数据?
检查带有/ Jekyll Liquid 的页面上是不是存在带有/ class x 的 div