检查 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
这也会覆盖您的配置。如果这不是一个选项,您需要手动执行此操作或使用 jq
、sed
或任何可用的方法。
更新:
如果您无权访问 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"
作为 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
这也会覆盖您的配置。如果这不是一个选项,您需要手动执行此操作或使用 jq
、sed
或任何可用的方法。
更新: 如果您无权访问 docker-daemon,例如因为您正在使用 harbor 提供的 kaniko within a docker, you can use the registry-api scripts 构建 docker 图像。请注意,它们是 python2.
以 morty's
DOCKER_CLI_EXPERIMENTAL
Enable experimental features for the cli (e.g.enabled
ordisabled
)
代码段因此变为:
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 中:
请注意,这将拉取图像(如果存在)。使用此解决方案前请注意管理费用。
只是
#!/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"