curl 如何使用Docker Registry API提取容器的信息?获取未授权

1yjd4xko  于 2022-11-13  发布在  Docker
关注(0)|答案(2)|浏览(225)

不久前,我读到一篇文章,标题为Inspecting Docker Images without pulling them,它深入到了使用REST调用执行docker inspect所需的特定API调用的细节。但是,我想知道,自从那篇文章写出来之后,Docker注册表API是否发生了变化。
本文详细介绍了您需要进行三次REST调用,以获取有关容器的信息。对于公共Docker注册表,它们如下所示:
1.发送到auth.docker.io以获取令牌的GET请求

curl "https://auth.docker.io/token?scope=repository:<image>:pull&service=registry.docker.io"

在这种情况下,image可以是nginxdocker-基本上是您要查找的任何图像。
1.检索清单列表的GET请求

curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json"
-H "Authorization: Bearer <token-from-step-1>"
"https://registry-1.docker.io/v2/<image>/manifests/<tag>"

这里的image与步骤1中的相同,tag可以是latest。关键是我们需要提取.config.digest处的值。这是我们在最终请求中使用的摘要字符串。
1.最后是一个GET请求,使用我们在步骤2中收到的摘要来检索容器配置

curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json"
-H "Authorization: Bearer <token-from-step-1>"
"https://registry-1.docker.io/v2/<image>/blobs/<digest-from-step-2>"

这将返回一些JSON,而我关心的字段是.config
我能够在一个私有的Docker注册表上成功地测试这个,尽管我不得不在那里做一些不同的auth.但是当我尝试按照公共Docker注册表的指南(我在上面的步骤中概述了)进行操作时,我遇到了相反的问题:步骤1给了我一个令牌,但这个令牌没有价值。每当我尝试在步骤2或3中使用它时,我得到的结果是:

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"docker","Action":"pull"}]}]}

有什么办法让它工作吗?

zlhcx6iw

zlhcx6iw1#

使用以下步骤,您可以检索任何公共容器映像的配置。
1.获取映像的相应令牌。请注意,您必须指定映像的全名(正式映像使用library存储库)。因此,NGINX image应被称为:library/nginx .

curl \
    --silent \
    "https://auth.docker.io/token?scope=repository:library/nginx:pull&service=registry.docker.io" \
    | jq -r '.token'
  • 为简洁起见,标记缩写为:* eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXV...

1.从清单中检索图像摘要。对于此请求,还需要指定有效的标记(此示例使用latest标记)。

curl \
    --silent \
    --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
    --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXV..." \
    "https://registry-1.docker.io/v2/library/nginx/manifests/latest" \
    | jq -r '.config.digest'

256:2bcb04bdb83f7c5dc30f00edaca1609a716bda1c7d2244d4f5fbbdfeff33da366c的一个新的数据库,它是一个新的数据库。
1.最后,使用以下请求获取容器配置。在URL中,必须指定第二步中的摘要。

curl \
    --silent \
    --location \
    --header "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXV..." \
    "https://registry-1.docker.io/v2/library/nginx/blobs/sha256:2bcb04bdb83f7c5dc30f0edaca1609a716bda1c7d2244d4f5fbbdfef33da366c" \
    | jq -r '.container_config'
  • 为简洁起见,输出已缩短:*
{
    "Hostname": "6c02a05b3d09",
    "Env": [
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "NGINX_VERSION=1.15.10-1~stretch",
        "NJS_VERSION=1.15.10.0.3.0-1~stretch"
    ],
    "Labels": {
        "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
    },
    "StopSignal": "SIGTERM"
}
k7fdbhmy

k7fdbhmy2#

本文详细介绍了您需要进行三次REST调用,以获取有关容器的信息。
关于图像
最后是一个GET请求,用于检索容器配置
映像配置
显示图像配置的脚本。它与专用注册表和Docker Hub一起使用。对于基本的身份验证注册表,您需要提供第二个参数(user:pass)。

#!/usr/bin/env bash
set -eu
image=$1
creds=${2-}

# https://github.com/moby/moby/blob/v20.10.18/vendor/github.com/docker/distribution/reference/normalize.go#L29-L57
# https://github.com/moby/moby/blob/v20.10.18/vendor/github.com/docker/distribution/reference/normalize.go#L88-L105
registry=${image%%/*}
if [ "$registry" = "$image" ] \
|| { [ "`expr index "$registry" .:`" = 0 ] && [ "$registry" != localhost ]; }; then
    registry=docker.io
else
    image=${image#*/}
fi
if [ "$registry" = docker.io ] && [ "`expr index "$image" /`" = 0 ]; then
    image=library/$image
fi
if [ "`expr index "$image" :`" = 0 ]; then
    tag=latest
else
    tag=${image#*:}
    image=${image%:*}
fi
if [ "$registry" = docker.io ]; then
    registry=https://registry-1.docker.io
elif ! [[ "$registry" =~ ^localhost(:[0-9]+)$ ]]; then
    registry=https://$registry
fi

r=`curl -sS "$registry/v2/" \
    -o /dev/null \
    -w '%{http_code}:%header{www-authenticate}'`
http_code=`echo "$r" | cut -d: -f1`
curl_args=(-sS -H 'Accept: application/vnd.docker.distribution.manifest.v2+json')
if [ "$http_code" = 401 ]; then
    if [ "$registry" = https://registry-1.docker.io ]; then
        header_www_authenticate=`echo "$r" | cut -d: -f2-`
        header_www_authenticate=`echo "$header_www_authenticate" | sed -E 's/^Bearer +//'`
        split_into_lines() {
            sed -Ee :1 -e 's/^(([^",]|"([^"]|\")*")*),/\1\n/; t1'
        }
        header_www_authenticate=`echo "$header_www_authenticate" | split_into_lines`
        extract_value() {
            sed -E 's/^[^=]+="(([^"]|\")*)"$/\1/; s/\\(.)/\1/g'
        }
        realm=$(echo "$header_www_authenticate" | grep '^realm=' | extract_value)
        service=$(echo "$header_www_authenticate" | grep '^service=' | extract_value)
        scope=repository:$image:pull
        token=`curl -sS "$realm?service=$service&scope=$scope" | jq -r .token`
        curl_args+=(-H "Authorization: Bearer $token")
    else
        curl_args+=(-u "$creds")
    fi
fi
manifest=`curl "${curl_args[@]}" "$registry/v2/$image/manifests/$tag"`
config_digest=`echo "$manifest" | jq -r .config.digest`
curl "${curl_args[@]}" -L "$registry/v2/$image/blobs/$config_digest" | jq -C

用法:

$ ./image-config.sh ruby
$ ./image-config.sh library/ruby            # same as the one above
$ ./image-config.sh docker.io/library/ruby  # same as the previous two
$ ./image-config.sh docker.io/library/ruby:3.0.4
$ ./image-config.sh myregistry.com/hello-world testuser:testpassword
$ ./image-config.sh localhost:5000/hello-world

关于使用API的几点说明:

  • 注册表是一个仓库的集合,比如GitHub,仓库的名称通常是user/name的形式(例如nginxproxy/nginx-proxy)。但对于官方存储库(所有实际上都以library/开始)可以省略第一段,(library/ruby-〉ruby)。也可能只有一个段(例如在私有注册表中),有时第一部分单独被称为仓库(示例)。
  • 存储库是图像的集合。其中一些图像被标记了。未标记的图像通常是在您使用相同的标记推送新版本的图像时产生的。
  • 一个旧的,但可能有点最新的relevant article(至少开始)。
  • 有关Docker Hub的注册表URL,请参阅此答案。
  • 不要期望spec中的所有东西都能工作。例如,Docker Hub没有实现/v2/_catalog路由。

相关问题