检查 image:tag 组合是否已存在于 docker 集线器上

Check if image:tag combination already exists on docker hub

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

即伪代码如下:

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=""; 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//tags/ > /dev/null
}

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

更新:

如果使用 Docker 注册表 v2(基于 this):

# set username and password
UNAME="user"
UPASS="password"

function docker_tag_exists() {
    TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${UNAME}'", "password": "'${UPASS}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)
    curl --silent -f --head -lL https://hub.docker.com/v2/repositories//tags// > /dev/null
}

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

我一直在努力让它为私有 docker 集线器存储库工作,最后决定改为编写一个 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_USER和DOCKER_PASSWORD...

DOCKER_USER=XXX DOCKER_PASSWORD=XXX config/docker/docker_hub.rb "NAMESPACE/REPO" "TAG" && echo 'latest'

如果验证成功且指定的标签不存在,此行将打印出'latest'!当我试图根据当前 git 分支获取标签时,我在我的 Vagrantfile 中使用了它:

git rev-parse --symbolic-full-name --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

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

登录

docker login -u $USER -p $PASSWORD $REGISTRY

检查是否存在:

docker manifest inspect $IMGNAME:$IMGTAG > /dev/null ; echo $?

docker 将 return 成功时为 0,失败时为 1。

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

将环境变量 DOCKER_CLI_EXPERIMENTAL 设置为 enabled(参见下面 Matěj 的回答)

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

echo '{"experimental": "enabled"}' > ~/.docker/config.json

这也会覆盖您的配置。如果这不是一个选项,您需要手动执行此操作或使用 jqsed 或任何可用的方法。

更新: 如果您无权访问 docker-daemon,例如因为您正在使用 harbor 提供的 kaniko within a docker, you can use the registry-api scripts 构建 docker 图像。请注意,它们是 python2.

morty's , notice that docker supports setting the experimental flag using environment variable 为基础:

DOCKER_CLI_EXPERIMENTAL Enable experimental features for the cli (e.g. enabled or disabled)

代码段因此变为:

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

你有没有试过类似的东西,简单地尝试拉标签并根据 return 代码决定是否推送?

#! /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 说它 "Cannot iterate over null"。去克服它。可以使用 ? 跳过不存在的块 这是对上述解决方案的修改,特别适用于 public 回购:

#!/usr/bin/env bash

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

if docker_image_tag_exists  ; then
    echo "true"
else
    echo "false"
fi

我使用 registry:2、私有 CA 和基本身份验证在我的 LAN 上建立了一个 docker 私有存储库。

我刚刚查看了官方 docker API 文档 (https://docs.docker.com/registry/spec/api/) 并提出了这个看起来非常优雅、易于调试、自定义并且 CICD/scripting 友好。

curl --silent -i -u "demoadmin":"demopassword" https://mydockerrepo.local:5000/v2/rancher/pause/manifests/3.1 | grep "200 OK"

--silient 去掉了一些额外的文本
-i 是 return 代码“200 OK”出现的原因

如果存在return代码为0,如果不存在return代码为1 您可以验证使用
Bash# echo $?

以上所有选项都假定您可以使用 username/password 进行身份验证。在很多情况下这是不方便的,例如在使用 Google Container Registry 时,首先要 运行 gcloud auth configure-docker gcr.io。该命令为 Docker 安装身份验证助手,您不想自己管理该令牌。

一个支持这些 docker 身份验证助手并且还允许获取清单的工具 - 就像实验性 Docker - 是 crane

使用起重机的例子:

# you would have done this already
gcloud auth configure-docker gcr.io;

# ensure we have crane installed
which crane || (echo 'installing crane' && GO111MODULE=on go get -u github.com/google/go-containerregistry/cmd/crane)

# check manifest
crane manifest ubuntu || echo "does not exist"