作为bash脚本的一部分,我想检查特定docker镜像:标签组合是否存在于docker hub上。此外,它将是一个私有仓库。
即伪代码如下:
tag = something
if image:tag already exists on docker hub:
Do nothing
else
Build and push docker image with that tag
作为bash脚本的一部分,我想检查特定docker镜像:标签组合是否存在于docker hub上。此外,它将是一个私有仓库。
即伪代码如下:
tag = something
if image:tag already exists on docker hub:
Do nothing
else
Build and push docker image with that tag
更新:请参考下文中的不使用Docker的解决方案。
使用Docker
这是我在gitlab中使用docker:stable镜像的解决方案。
登录
docker login -u $USER -p $PASSWORD $REGISTRY
docker manifest inspect $IMGNAME:$IMGTAG > /dev/null ; echo $?
Docker执行成功将返回0,失败则返回1。
如果您收到警告:请更新Docker或启用实验性客户端功能:
将环境变量DOCKER_CLI_EXPERIMENTAL
设置为 enabled
(参见以下Matěj的回答)
或者按照原始回答进行调整配置:
echo '{"experimental": "enabled"}' > ~/.docker/config.json
这也将覆盖您的配置。如果这不是一个选项,您需要手动执行或使用 jq
、sed
或其他可用工具。
无需 Docker 进行测试
jq '. + {"experimental": "enabled"}' < ~/.docker/config.json | sponge ~/.docker/config.json
。该命令用于在Docker配置文件中添加实验性功能,并使用sponge
命令将更改写回到原始配置文件中,避免了常见的重定向问题。 - mgalgsDOCKER_CLI_EXPERIMENTAL=enabled
来避免更改您的 Docker 配置文件。 - Chris Deacy请尝试这个
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:
# 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/$1/tags/$2/ > /dev/null
}
if docker_tag_exists library/nginx 1.7.5; then
echo exist
else
echo not exists
fi
aws ecr describe-images --repository-name <repo> --image-ids imageTag=latest
。这将避免编写任何 curl/授权的需求。 - Nikhil OwalekarDocker version 20.10.7
,看起来您不再需要启用 DOCKER_CLI_EXPERIMENTAL
。 - dsaydon我在本地局域网中使用registry:2、私有CA和基本认证搭建了一个Docker私有仓库。
我刚刚查看了官方的Docker API文档(https://docs.docker.com/registry/spec/api/),并想出了这个解决方案,它看起来相当简洁、易于调试、自定义并且适合CICD/脚本编写。
curl --silent -i -u "demoadmin":"demopassword" https://mydockerrepo.local:5000/v2/rancher/pause/manifests/3.1 | grep "200 OK"
--silient可以去除一些额外的文本
-i是让返回代码“200 OK”显示的关键
如果存在则返回代码为0,如果不存在则返回代码为1
你可以使用以下命令验证:
Bash# echo $?
这里有一个有用的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"
docker pull
命令会破坏该镜像与正在运行的所有容器之间的关联。请注意,此函数将对正在运行的容器产生副作用,需谨慎使用! - Ilia Sidorenko这是对Evgeny Oskin的解决方案的小改进。当涉及到一个尚未创建的用户repo时,jq会提示"Cannot iterate over null"。为了克服这个问题,可以使用?跳过不存在的块。 以下是针对公共repo的上述解决方案的修改:
最初的回答:
#!/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 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_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注册表,您可以尝试以下方法:
function docker_tag_exists() {
curl --silent -f -lSL http://localhost:5000/v2/$1/manifests/$2 > /dev/null
}
if docker_tag_exists image_on_local latest; then
echo exists
else
echo not exists
fi
docker manifest inspect $registry/$imageName:$tag > /dev/null 2>&1 && echo yes || echo no