bash 检查 docker hub 上是否已经存在 image:tag 组合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32113330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:04:14  来源:igfitidea点击:

Check if image:tag combination already exists on docker hub

bashdockerdockerhub

提问by rgareth

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.

作为 bash 脚本的一部分,我想检查 docker hub 上是否存在特定的 docker image:tag 组合。此外,它将是一个私有存储库。

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

采纳答案by Evgeny Oskin

Please try this one

请试试这个

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


Update:

更新:

In case of usage Docker Registry v2 (based on this):

如果使用 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//tags/?page_size=10000 | jq -r "[.results | .[] | .name == \"\"] | any")
    test $EXISTS = true
}

if docker_tag_exists library/nginx 1.7.5; then
    echo exist
else 
    echo not exists
fi

回答by morty

Update:Docker-Free solution see below

更新:Docker-Free 解决方案见下文

Using Docker

使用 Docker

This is the solution I use with gitlab using the docker:stable image.

这是我使用 docker:stable 图像与 gitlab 一起使用的解决方案。

Make sure experimental client-features are enabled:

确保启用实验性客户端功能

Set the environment variable DOCKER_CLI_EXPERIMENTALto enabled(See Matěj's answer below)

将环境变量设置DOCKER_CLI_EXPERIMENTALenabled(参见下面 Matěj 的回答)

Alternatively adjust the config (original answer):

或者调整配置(原始答案):

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, sedor whatever you have available.

这也将覆盖您的配置。如果这是不是一种选择,你需要做的是手动或使用jqsed或任何你有可用。

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.

docker 将在成功时返回 0 或在失败时返回 1。

Update:If you don't have access to a docker-daemon, e.g. because you are building a docker image using kanikowithin a docker, you can use the registry-api scriptsprovided by harbor. Note that they are python2.

更新:如果您无权访问docker-daemon,例如因为您在docker中使用kaniko构建docker 镜像,您可以使用由Harbor提供的registry-api 脚本。请注意,它们是python2。

回答by Matěj Laitl

To build on morty's answer, notice that docker supports setting the experimental flag using environment variable:

要以morty回答为基础,请注意docker支持使用环境变量设置实验标志

DOCKER_CLI_EXPERIMENTALEnable experimental features for the cli (e.g. enabledor disabled)

DOCKER_CLI_EXPERIMENTAL为 cli 启用实验性功能(例如enableddisabled

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

回答by mayankcpdixit

Easiest:

最简单:

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

Pulls & prints successif image exists, or prints failedif it doesn't:

如果图像存在则拉取并打印成功,如果不存在则打印失败

You can even export it in a var if using in bash script:

如果在 bash 脚本中使用,您甚至可以将其导出到 var 中:

enter image description here

在此处输入图片说明

Note that this will pull the image if it exists. Beware of the overhead cost before using this solution.

请注意,这将拉取图像(如果存在)。在使用此解决方案之前,请注意管理费用。

回答by Elifarley

Here's a Bash function that will help:

这是一个 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'
}

Usage example:

用法示例:

docker_image_exists elifarley/docker-dev-env:alpine-sshd && \
  echo EXISTS || \
  echo "Image does not exist"

回答by Romain

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

回答by silk

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:

只是Evgeny Oskin 解决方案的一个小改进。当涉及尚未创建的用户存储库时,jq 表示它“无法迭代 null”。去克服它。可以跳过不存在的块吗?这是对上述解决方案的修改,特别适用于公共回购:

#!/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

回答by ramigg

I like solutions based on docker.

我喜欢基于 docker 的解决方案。

This oneliner is what I use in our CI:

这个 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

回答by neokyle

I have a docker private repo stood up on my LAN using registry:2, private CA, and basic auth.

我有一个使用 registry:2、私有 CA 和基本身份验证在我的 LAN 上的 docker 私有存储库。

I just looked at the official docker API docs (https://docs.docker.com/registry/spec/api/) and came up with this solution which seems pretty elegant, easy to debug, customize, and is CICD/scripting friendly.

我刚刚查看了官方 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 gets rid of some extra text
-i is what makes the return code "200 OK" show up

--silient 去掉了一些额外的文本
-i 是返回代码“200 OK”显示的原因

if it exists return code is 0, if doesn't exist return code is 1 you can verify that using
Bash# echo $?

如果存在返回码为 0,如果不存在返回码为 1 您可以验证使用
Bash# echo $?

回答by crizCraig

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