Bash 检查docker hub上是否已存在图像:标记组合

Bash 检查docker hub上是否已存在图像:标记组合,bash,docker,dockerhub,Bash,Docker,Dockerhub,作为bash脚本的一部分,我想检查docker hub上是否存在特定的docker image:tag组合。此外,它将是一个私有存储库 i、 e.伪代码如下所示: tag = something if image:tag already exists on docker hub: Do nothing else Build and push docker image with that tag 下面是一个Bash函数,它将有助于: docker_image_exists() {

作为bash脚本的一部分,我想检查docker hub上是否存在特定的docker image:tag组合。此外,它将是一个私有存储库

i、 e.伪代码如下所示:

tag = something
if image:tag already exists on docker hub:
    Do nothing
else
    Build and push docker image with that tag

下面是一个Bash函数,它将有助于:

docker_image_exists() {
  local image_full_name="$1"; shift
  local wait_time="${1:-5}"
  local search_term='Pulling|is up to date|not found'
  local result="$((timeout --preserve-status "$wait_time" docker 2>&1 pull "$image_full_name" &) | grep -v 'Pulling repository' | egrep -o "$search_term")"
  test "$result" || { echo "Timed out too soon. Try using a wait_time greater than $wait_time..."; return 1 ;}
  echo $result | grep -vq 'not found'
}
用法示例:

docker_image_exists elifarley/docker-dev-env:alpine-sshd && \
  echo EXISTS || \
  echo "Image does not exist"
请试试这个

function docker_tag_exists() {
    curl --silent -f -lSL https://index.docker.io/v1/repositories/$1/tags/$2 > /dev/null
}

if docker_tag_exists library/nginx 1.7.5; then
    echo exist
else 
    echo not exists
fi

更新:

如果使用Docker Registry v2(基于):


我在一个私有docker hub存储库中努力使其工作,最后决定编写一个ruby脚本,该脚本从今天起就可以使用。请随意使用

#!/usr/bin/env ruby
require 'base64'
require 'net/http'
require 'uri'

def docker_tag_exists? repo, tag
  auth_string = Base64.strict_encode64 "#{ENV['DOCKER_USER']}:#{ENV['DOCKER_PASSWORD']}"
  uri = URI.parse("https://registry.hub.docker.com/v1/repositories/#{repo}/tags/#{tag}")
  request = Net::HTTP::Get.new(uri)
  request['Authorization'] = "Basic #{auth_string}"
  request['Accept'] = 'application/json'
  request['Content-Type'] = 'application/json'
  response = Net::HTTP.start(request.uri.hostname, request.uri.port, use_ssl: true) do |http|
    http.request(request)
  end
  (response.body == 'Tag not found') ? 0 : 1
end

exit docker_tag_exists? ARGV[0], ARGV[1]
注意:您需要指定DOCKER_用户和DOCKER_密码来调用此项,如

DOCKER\u USER=XXX DOCKER\u PASSWORD=XXX config/DOCKER/DOCKER\u hub.rb“NAMESPACE/REPO”“TAG”&&echo“latest”

如果身份验证成功且指定的标记不存在,此行将打印“latest”!在尝试基于当前git分支获取标记时,我在我的Vagrantfile中使用了这个:


git rev parse——符号全名——abbrev ref HEAD

我喜欢基于docker的解决方案

这是我在CI中使用的一行:

 docker run --rm anoxis/registry-cli -l user:password -r registry-url -i docker-name | grep -q docker-tag || echo do something if not found

更新:无码头工人解决方案见下文

使用Docker

这是我使用docker:stable映像与gitlab一起使用的解决方案

登录

docker登录-u$USER-p$PASSWORD$REGISTRY
检查它是否在那里:

docker pull alpine:invalid > /dev/null && echo "success" || echo "failed"
docker清单检查$IMGNAME:$IMGTAG>/dev/null;回声$?
docker在成功时返回0,在失败时返回1

如果收到警告:更新Docker或启用实验客户端功能

将环境变量设置为启用(参见下面Matěj的答案)

或者调整配置(原始答案):

echo'{“实验”:“enabled”}>~/.docker/config.json
这也将覆盖您的配置。如果这不是一个选项,您需要手动执行或使用
jq
sed
或任何可用的工具

更新:
如果您没有访问docker守护程序的权限,例如,因为您正在docker中使用构建docker映像,您可以使用harbor提供的。请注意,它们是python2。

您可以尝试拉拽,看看是否是最新的(如果远程设备较新,您可能需要先标记本地映像):

要在的基础上构建,请注意docker支持:

DOCKER\u CLI\u EXPERIMENTAL
为CLI启用实验功能(例如
已启用
已禁用

因此,代码段变为:

tag=something
if DOCKER_CLI_EXPERIMENTAL=enabled docker manifest inspect $image:$tag >/dev/null; then
    Do nothing
else
    Build and push docker image with that tag
fi

您是否尝试过类似的方法,只是尝试拉标签并根据返回代码决定推还是不推

#! /bin/bash

if docker pull hello-world:linux > /dev/null; then
  echo "already exist -> do not push"
else
  echo "does not exist -> push"
fi

最简单:

docker pull alpine:invalid > /dev/null && echo "success" || echo "failed"
如果图像存在,则拉取并打印成功,如果图像不存在,则打印失败

如果在bash脚本中使用,甚至可以将其导出到var中:


请注意,如果图像存在,这将拉动图像。在使用此解决方案之前,请注意管理费用。

这只是一个小小的改进。对于尚未创建的用户repo,jq表示它“不能在null上迭代”。为了克服它。可以跳过带有 以下是对上述解决方案的修改,特别适用于公开回购:

#!/usr/bin/env bash

function docker_image_tag_exists() {
    EXISTS=$(curl -s https://hub.docker.com/v2/repositories/$1/tags/?page_size=10000 | jq -r "[.results? | .[]? | .name == \"$2\"] | any")
    test ${EXISTS} = true
}

if docker_image_tag_exists $1 $2; then
    echo "true"
else
    echo "false"
fi

我有一个docker私人回购站在我的局域网上使用注册表:2,私人CA和基本认证

我刚刚看了官方的docker API文档()并提出了这个解决方案,它看起来非常优雅,易于调试、自定义,并且对CICD/脚本友好

curl --silent -i -u "demoadmin":"demopassword" https://mydockerrepo.local:5000/v2/rancher/pause/manifests/3.1 | grep "200 OK"
--silient删除了一些额外的文本
-i是返回码“200OK”出现的原因

如果存在,返回码为0;如果不存在,返回码为1 您可以使用

Bash#echo$?

以上所有选项都假定您可以使用用户名/密码进行身份验证。在很多情况下,这是不方便的,例如在使用Google容器注册表时,首先要运行
gcloud auth configure docker gcr.io
。该命令为Docker安装了一个身份验证帮助器,您不想自己管理该令牌

一个支持这些docker身份验证帮助程序的工具是

使用起重机的示例:

#您应该已经这样做了
gcloud auth配置docker gcr.io;
#确保我们安装了起重机
哪个起重机(echo'installing crane'&GO111MODULE=on-go-get-u github.com/google/go-containerregistry/cmd/crane)
#检查舱单
crane manifest ubuntu | | echo“不存在”

我对这里的一些答案有很多问题。在我看来,最简单的答案是来自@Evgeny Oskin的公认答案

curl有一半起作用,但由于某些原因,没有找到包含字符的标记,例如
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

最后,我用以下解决方案修复了它:

curl -s -u "$DOCKERHUB_USER:$DOCKERHUB_PSWD" https://index.docker.io/v1/repositories/$company/$dockerHubRepo/tags | jq '.[] | select (.name == "$dockerImage")'
这将在dockerhub中为每个标记获取json文件,然后我们执行一些jq魔术来过滤图像并检查它是否确实存在


如果图像不存在,则返回的输出将为空。

我相信我们也有同样的问题。不确定这是否与您相关,但我们正在运行自己的Docker注册表,它公开了一个您可以使用的API。我可能会在我的CI构建中添加一个查询API的步骤,以便它不会覆盖现有的标记。我很惊讶这不是docker repository API的一部分……可以用来检查图像是否驻留在docker注册表中。我今天发布了1.0.0版。这里有人知道在Docker的哪个地方可以使用此功能吗?我想发送一个请求
curl -s -u "$DOCKERHUB_USER:$DOCKERHUB_PSWD" https://index.docker.io/v1/repositories/$company/$dockerHubRepo/tags | jq '.[] | select (.name == "$dockerImage")'