Проверьте, существует ли комбинация изображения: тега в докер-хабе.

Как часть скрипта bash, я хочу проверить, существует ли в Docker Hub особая комбинация docker image:tag. Кроме того, это будет частный репозиторий.

то есть псевдокод будет выглядеть так:

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

person rgareth    schedule 20.08.2015    source источник
comment
Я считаю, что у нас та же проблема. Не уверен, что это имеет отношение к вам, но у нас есть собственный реестр Docker, и он предоставляет API, который вы можете использовать. docs.docker.com/registry/spec/api/#listing- image-tags Я, вероятно, добавлю шаг в свою сборку CI, который запрашивает API, чтобы он не перезаписывал существующий тег.   -  person Christoffer    schedule 12.11.2015
comment
Я удивлен, что это не является частью API репозитория докеров....   -  person kgx    schedule 04.02.2016
comment
Можно использовать dip, чтобы проверить, находится ли изображение в реестре докеров. Я выпускаю версию 1.0.0 сегодня.   -  person 030    schedule 05.11.2019
comment
Кто-нибудь здесь знает, где было бы правильно попросить об этой функции в Docker? Я хотел бы отправить запрос на эту функцию команде Docker (или понять, почему это не будет хорошим кандидатом для использования в Docker).   -  person akki    schedule 02.06.2020


Ответы (13)


Примерьте вот это

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
person Evgeny Oskin    schedule 27.09.2016
comment
как насчет реестров, отличных от docker.io? - person Ilia Sidorenko; 22.12.2016
comment
@WayNo, что ты используешь? Поделитесь ссылкой на документацию. - person Evgeny Oskin; 25.12.2016
comment
@WayNo Я обновил сообщение, указав функцию для Docker Registry v2. Я считаю, что для использования этой функции с реестрами, отличными от docker.io, вы должны сделать следующее: использовать UNAME и UPASS, полученные из команды aws ecr get-login; и aws_account_id.dkr.ecr.region.amazonaws.com в качестве хоста. - person Evgeny Oskin; 11.01.2017
comment
Это будет работать для ECR: aws ecr describe-images --repository-name <repo> --image-ids imageTag=latest Это устранит необходимость создания каких-либо завитков/авторизации. - person Nikhil Owalekar; 16.11.2017
comment
Для AWS это сработало для меня: docs.aws.amazon. com/AmazonECR/latest/userguide/ - person Richard Nienaber; 26.11.2018
comment
в версии 2, чтобы избежать синтаксического анализа разбитого на страницы списка тегов, просто сделайте запрос HEAD для того, который вам нужен: curl --silent -f --head -lSL https://registry.example.com/v2/$1/manifests/$2 > /dev/null - person rymo; 04.06.2019
comment
Протестировал это с несколькими репозиториями, с которыми я сейчас работаю, параметр размера страницы перестает работать после ~ 1400, насколько я могу судить. Вы спросите, почему в этих репозиториях так много тегов? Ну .... это хороший вопрос. - person Kyle Jones; 30.04.2020
comment
Спасибо, @KyleJones! Я улучшил сценарий, удалив ответ с разбивкой на страницы. - person Evgeny Oskin; 28.06.2020

Обновление: решение без 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 (см. ответ Матея ниже)

В качестве альтернативы отрегулируйте конфигурацию (исходный ответ):

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

Это также перезапишет вашу конфигурацию. Если это не вариант, вам нужно сделать это вручную или использовать jq, sed или что-то другое, что у вас есть.

Обновление: если у вас нет доступа к Docker-daemon, например. поскольку вы создаете образ докера с помощью kaniko внутри докера, вы можете использовать скрипты registry-api, предоставленные гаванью. Обратите внимание, что это python2.

person Morty    schedule 29.08.2018
comment
Жаль, что это все еще экспериментальный - person Mark Tickner; 03.09.2018
comment
на самом деле ваша первая команда перезапишет весь файл конфигурации, поэтому стоит добавить эту строку, отредактировав файл - person vladkras; 13.01.2019
comment
Однострочник для ленивых: jq '. + {"experimental": "enabled"}' < ~/.docker/config.json | sponge ~/.docker/config.json - person mgalgs; 09.04.2019
comment
Как упоминалось в другом ответе ниже, вы можете избежать изменения файла конфигурации докера, используя DOCKER_CLI_EXPERIMENTAL=enabled - person Chris Deacy; 05.08.2019
comment
@MarkTickner, к сожалению, он все еще не работает (я получаю сообщение о том, что манифест не найден, а pull извлекает изображение). - person 9ilsdx 9rvj 0lo; 10.12.2019
comment
Почему это все еще экспериментально 2 года спустя? - person jones-chris; 02.07.2020
comment
это кажется неэкспериментальным уже. Я только что установил докер, и без включения каких-либо экспериментальных вещей он у меня работает. - person igagis; 22.02.2021

Чтобы построить на morty answer, обратите внимание, что docker поддерживает установку экспериментального флага с использованием среды переменная:

DOCKER_CLI_EXPERIMENTAL Включить экспериментальные функции для cli (например, 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
person Matěj Laitl    schedule 26.05.2019
comment
Я использую docker cli Docker version 20.10.7, и кажется, что вам больше не нужно включать DOCKER_CLI_EXPERIMENTAL - person dsaydon; 09.06.2021

Самый простой:

docker pull alpine:invalid > /dev/null && echo "success" || echo "failed"

Извлекает и печатает success, если изображение существует, или печатает failed, если нет:

Вы даже можете экспортировать его в var при использовании в сценарии bash:

введите здесь описание изображения

Обратите внимание, что это приведет к извлечению изображения, если оно существует. Остерегайтесь накладных расходов, прежде чем использовать это решение.

person mayankcpdixit    schedule 12.07.2019
comment
Обратите внимание, что это вытянет контейнер, если он существует. Вытягивание даже небольшого альпийского — это довольно накладные расходы только для того, чтобы получить эту информацию. Не говоря уже о нескольких GB-Image, которые часто используются в средах CI. - person Morty; 04.04.2020
comment
Истинный. Я не мог не согласиться. Я добавил эту информацию в этот ответ. Спасибо за отзыв. - person mayankcpdixit; 14.04.2020
comment
Это идеально подходит для моего кэширования слоев AWS CodeBuild. Я просто хочу попытаться выдернуть его, и мне все равно, существует он или нет. Он все равно будет построен и кэширован - person nitsujri; 12.05.2021
comment
Если предполагается, что изображение не не существует, то это не проблема. Кроме того, в том маловероятном случае, если изображение действительно существует, например, когда вы случайно создали выпуск с использованием старого тега, это автоматически перезапишет ваше новое изображение до того, что было раньше, что весьма полезно. - person rustyx; 27.07.2021

Вот функция 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"
person Elifarley    schedule 13.06.2016
comment
Похоже, что он проверяет существование образа, пытаясь вытащить его, что является излишним, и в случае успеха он изменит изображения на локальном хосте. - person Vince Bowdren; 17.08.2016
comment
Он пытается извлечь его, но сценарий прерывает операцию, если извлечение изображения занимает больше времени, чем выбранное значение тайм-аута (по умолчанию 5 секунд). - person Elifarley; 18.08.2016
comment
Ах, достаточно справедливо. Может быть, было бы полезно добавить немного пояснений к ответу, проанализировав, что он делает и чего не делает? - person Vince Bowdren; 18.08.2016
comment
может ли кто-нибудь написать сценарий bash, который вместо этого использует API? - person Nick D; 21.09.2016
comment
После запуска это выглядит так, как будто docker pull на изображении разрывает связь этого изображения со всеми запущенными контейнерами этого изображения. Будьте осторожны, эта функция вызовет побочные эффекты на ваших запущенных контейнерах! - person Ilia Sidorenko; 11.01.2017

У меня есть частное репозиторий Docker, установленное в моей локальной сети с использованием реестра: 2, частного ЦС и базовой аутентификации.

Я только что просмотрел официальную документацию API Docker (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 $?

person neokyle    schedule 15.04.2020
comment
Я хотел знать, как проверить, существует ли тег в частном репо через rest, не выполняя /v2/imagename/tags/list, и это идеальный ответ! По какой-то причине было очень сложно найти этот ответ в stackoverflow. - person Patrick Riordan; 24.12.2020

Просто небольшое улучшение решения Евгения Оскина. Когда дело доходит до пользовательского репозитория, который еще не создан, 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
person silk    schedule 16.07.2019

Я изо всех сил пытался заставить это работать для частного репозитория концентратора докеров и, наконец, решил вместо этого написать сценарий 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

person mfittko    schedule 05.10.2017

Мне нравятся решения на основе докера.

Этот 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
person ramigg    schedule 16.04.2018
comment
Вам следует подробнее остановиться на различных частях вашей команды. Похоже, это будет приятная команда, однако часть -i docker-name, в частности, сбивает меня с толку, и я понятия не имею, что туда вставить. - person Bwvolleyball; 02.04.2019

Вы можете просто попробовать потянуть и посмотреть, обновлены ли вы (вы можете сначала пометить свое локальное изображение, хотя на случай, если удаленный новее):

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
person crizCraig    schedule 22.04.2019

Все приведенные выше варианты предполагают, что вы можете аутентифицироваться, используя имя пользователя/пароль. Во многих случаях это неудобно, например, при использовании Google Container Registry, для которого сначала нужно запустить gcloud auth configure-docker gcr.io. Эта команда устанавливает помощник проверки подлинности для Docker, и вы не захотите самостоятельно управлять этим токеном.

Одним из инструментов, который поддерживает эти помощники по проверке подлинности 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"
person Herman    schedule 02.12.2020

У меня было много проблем с некоторыми ответами здесь. Самым простым, на мой взгляд, является принятый ответ от @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, чтобы отфильтровать изображение и убедиться, что оно действительно существует.

Если изображение не существует, возвращаемый вывод будет пустым.

person Toofy    schedule 03.06.2021

Вы пробовали что-то подобное, просто пытаясь вытащить тег и решив, нажать или нет, по коду возврата?

#! /bin/bash

if docker pull hello-world:linux > /dev/null; then
  echo "already exist -> do not push"
else
  echo "does not exist -> push"
fi
person Romain    schedule 31.05.2019
comment
почему вывод в dev/null создает истинное или ложное значение? - person a3y3; 08.03.2020
comment
@ a3y3 вывод в dev/null просто для того, чтобы не печатать вывод команды. Тест основан только на коде возврата команды (успешно, если изображение существует, в противном случае). - person Romain; 09.03.2020