As part of a bash script, I want to check if a particularly docker image:tag combination exists on docker hub. Also, it will be a private repository.
i.e. the pseudocode would be like:
tag = something
if image:tag already exists on docker hub:
Do nothing
else
Build and push docker image with that tag
Please try this one
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
Update:
In case of usage Docker Registry v2 (based on 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)
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
This is the solution I use with gitlab using the docker:stable image.
Make sure experimental client-features are enabled:
echo '{"experimental": "enabled"}' > ~/.docker/config.json
This will also overwrite your config. If that is not an option you need to do that manually or use jq, sed or whatever you have available.
Login
docker login -u $USER -p $PASSWORD $REGISTRY
Check whether it's there:
docker manifest inspect $IMGNAME:$IMGTAG > /dev/null ; echo $?
docker will return 0 on success or 1 on failure.
To build on morty's answer, notice that docker supports setting the experimental flag using environment variable:
DOCKER_CLI_EXPERIMENTALEnable experimental features for the cli (e.g.enabledordisabled)
The snippet therefore becomes:
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
Here's a Bash function that will help:
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'
}
Usage example:
docker_image_exists elifarley/docker-dev-env:alpine-sshd && \
echo EXISTS || \
echo "Image does not exist"
I like solutions based on docker.
This oneliner is what I use in our 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
Just a small improvement of Evgeny Oskin's solution. When it comes to a user repo that hasn't been created yet, jq says that it "Cannot iterate over null". To overcome it. one can skip not present blocks with ? Here is a modification to above mentioned solution that is applicable to a public repo in particular:
#!/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
I was struggling getting this to work for a private docker hub repository and finally decided to write a ruby script instead, which works as of today. Feel free to use!
#!/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]
Note: you need to specify DOCKER_USER and DOCKER_PASSWORD when calling this like...
DOCKER_USER=XXX DOCKER_PASSWORD=XXX config/docker/docker_hub.rb "NAMESPACE/REPO" "TAG" && echo 'latest'
This line would print out 'latest', if authentication is successful and the specified tag does not exists! I was using this in my Vagrantfile when trying to fetch a tag based on the current git branch:
git rev-parse --symbolic-full-name --abbrev-ref HEAD
You could just try pulling and see if you're up to date (You may want to tag your local image first though in case the remote is newer):
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
Have you tried something like that, simply trying to pull the tag and deciding to push or not according to the return code?
#! /bin/bash
if docker pull hello-world:linux > /dev/null; then
echo "already exist -> do not push"
else
echo "does not exist -> push"
fi
来源:https://stackoverflow.com/questions/32113330/check-if-imagetag-combination-already-exists-on-docker-hub
