Проверьте, существует ли комбинация image:tag в Docker Hub
Как часть bash-скрипта, я хочу проверить, существует ли на докере-концентраторе определенная комбинация образа: тега докера. Также это будет частный репозиторий.
то есть псевдокод будет выглядеть так:
tag = something
if image:tag already exists on docker hub:
Do nothing
else
Build and push docker image with that tag
15 ответов
Это решение, которое я использую с gitlab с помощью docker: stable image.
Убедитесь, что экспериментальные функции клиента включены:
echo '{"experimental": "enabled"}' > ~/.docker/config.json
Это также перезапишет ваш конфиг. Если это не вариант, вам нужно сделать это вручную или использовать jq
, sed
или что у вас есть в наличии.
Авторизоваться
docker login -u $USER -p $PASSWORD $REGISTRY
Проверьте, есть ли это:
docker manifest inspect $IMGNAME:$IMGTAG > /dev/null ; echo $?
Докер вернет 0 в случае успеха или 1 в случае ошибки.
Примерьте вот это
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)
EXISTS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/$1/tags/?page_size=10000 | jq -r "[.results | .[] | .name == \"$2\"] | any")
test $EXISTS = true
}
if docker_tag_exists library/nginx 1.7.5; then
echo exist
else
echo not exists
fi
Чтобы основываться на morty, обратите внимание, что docker поддерживает установку экспериментального флага с помощью переменной среды:
DOCKER_CLI_EXPERIMENTAL
Включить экспериментальные функции для клиента (например,enabled
или же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
Самый простой:
docker pull alpine:invalid > /dev/null && echo "success" || echo "failed"
Извлекает и печатает успешно, если изображение существует, или печатает не удалось, если его нет:
Вы даже можете экспортировать его в var, если используете bash-скрипт:
У меня есть частное репозиторий докеров в моей локальной сети с использованием реестра:2, частного центра сертификации и базовой аутентификации.
Я только что посмотрел официальные документы 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 $?
Просто небольшое улучшение решения Евгения Оськина. Когда дело доходит до пользовательского репозитория, который еще не был создан, jq говорит, что он "не может перебрать ноль". Чтобы преодолеть это. можно пропустить не существующие блоки с ? Вот модификация вышеупомянутого решения, которая применима, в частности, к публичному репо:
#!/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
Вот функция 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"
Мне нравятся решения, основанные на докере.
Этот oneliner - то, что я использую в нашем 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
Вы пробовали что-то подобное, просто пытаясь вытащить тег и решили нажать или нет в соответствии с кодом возврата?
#! /bin/bash
if docker pull hello-world:linux > /dev/null; then
echo "already exist -> do not push"
else
echo "does not exist -> push"
fi
Все вышеперечисленные варианты предполагают, что вы можете аутентифицироваться, используя имя пользователя / пароль. Во многих случаях это неудобно, например, при использовании реестра контейнеров Google, для которого можно запустить
gcloud auth configure-docker gcr.io
первый. Эта команда устанавливает помощник аутентификации для Docker, и вы не захотите самостоятельно управлять этим токеном.
Один из инструментов, который поддерживает этих помощников проверки подлинности докеров, а также позволяет получить манифест, как экспериментальный Docker, - это кран.
Пример использования крана:
# 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"
Если вы запрашиваете у концентратора наличие тега, убедитесь, что вы используете запрос HEAD, а не GET. Запрос GET учитывается в вашем лимите скорости. Сценарий, который делает это специально для Docker Hub, поддерживает только типы носителей Docker и анонимные входы в систему, скорость которых ограничена вашим запрашивающим IP-адресом, выглядит так:
$ more ~/data/docker/registry-api/manifest-v2-head.sh
#!/bin/sh
ref="${1:-library/ubuntu:latest}"
sha="${ref#*@}"
if [ "$sha" = "$ref" ]; then
sha=""
fi
wosha="${ref%%@*}"
repo="${wosha%:*}"
tag="${wosha##*:}"
if [ "$tag" = "$wosha" ]; then
tag="latest"
fi
api="application/vnd.docker.distribution.manifest.v2+json"
apil="application/vnd.docker.distribution.manifest.list.v2+json"
token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repo}:pull"
\
| jq -r '.token')
curl -H "Accept: ${api}" -H "Accept: ${apil}" \
-H "Authorization: Bearer $token" \
-I -s "https://registry-1.docker.io/v2/${repo}/manifests/${sha:-$tag}"
Чтобы работать с другими реестрами, обрабатывать больше типов носителей (например, типы OCI) и обрабатывать входы в систему, используйте такой инструмент, как кран, skopeo или мой собственный regclient:
# the "image digest" command uses a HEAD instead of a GET
if regctl image digest registry.example.com/repo:tag >/dev/null 2>&1; then
echo tag exists
else
echo tag does not exist
fi
Я изо всех сил пытался заставить это работать для частного хранилища док-хабов и наконец решил вместо этого написать скрипт 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'
Эта строка выведет "последний", если аутентификация прошла успешно, а указанный тег не существует! Я использовал это в своем Vagrantfile при попытке извлечь тег на основе текущей ветви git:
git rev-parse --symbolic-full-name --abbrev-ref HEAD
Вы можете просто попробовать потянуть и посмотреть, если вы в курсе (вы можете сначала пометить локальное изображение, хотя в случае, если пульт более новый):
docker pull deepdriveio/deepdrive:env-3.0
env-3.0: Pulling from deepdriveio/deepdrive
Digest: sha256:3b6b6514f79a551b47896f908a2de00b55df1db22f5908c8436feaa12310dfa3
Status: Image is up to date for deepdriveio/deepdrive:env-3.0
Для локального реестра докеров вы можете попробовать следующее:
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
У меня было много проблем с некоторыми ответами здесь. Самый простой, на мой взгляд, принятый ответ от @Evgeny Oskin.
Половина завитка работала, но по некоторым причинам теги включали такие символы, как
_
,
-
,
.
не были найдены, и я получал 404.
В конце концов я исправил это следующим решением:
curl -s -u "$DOCKERHUB_USER:$DOCKERHUB_PSWD" https://index.docker.io/v1/repositories/$company/$dockerHubRepo/tags | jq '.[] | select (.name == "$dockerImage")'
Это получит файл json в dockerhub для каждого отдельного тега, а затем мы сделаем некоторую магию jq, чтобы отфильтровать изображение и проверить, действительно ли оно существует.
Если изображение не существует, возвращаемый результат будет пустым.