如何使用 Docker 注册表 HTTP API V2 获取 docker 注册表中所有存储库的列表?

问题描述 投票:0回答:5

与我合作的外部组织允许我访问私有(受身份验证令牌保护的)docker 注册表,最终我希望能够使用 docker 的 HTTP API V2 查询此注册表,以获得所有列表注册表中可用的存储库和/或图像。

但在此之前,我首先想获得一些在公共注册表(例如 Docker Hub)上构建这些类型的 API 查询的基本实践。因此,我继续在 Docker Hub 上使用用户名和密码注册了自己,还查阅了 API V2 文档,其中指出可以请求进行 API 版本检查,如下所示:

GET /v2/

或请求存储库列表,如下:

GET /v2/_catalog

使用curl以及我用来注册Docker Hub帐户的用户名和密码,我尝试在命令行构建一个GET请求:

stachyra> curl -u stachyra:<my_password> -X GET https://index.docker.io/v2/
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
stachyra> curl -u stachyra:<my_password> -X GET https://index.docker.io/v2/_catalog
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"registry","Class":"","Name":"catalog","Action":"*"}]}]}

当然,我用我的实际帐户密码代替了

<my_password>

我一直期望此查询得到的响应是一条巨大的 json 消息,其中列出了数千个存储库名称,但 API 似乎拒绝了我的 Docker Hub 凭据。

问题 1: 我是否有 docker hub 注册表的正确 URL (

index.docker.io
)? (我首先根据命令行工具
docker info
返回的状态信息做出了这个假设,所以我有充分的理由认为它是正确的。)

问题 2: 假设我拥有注册表服务本身的正确 URL,为什么我的查询会返回“UNAUTHORIZED”错误代码?当我尝试通过网络登录 hub.docker.com 时,我的帐户凭据工作得很好,那么这两种情况有什么区别?

rest docker restful-authentication dockerhub docker-api
5个回答
17
投票

我有正确的网址吗

  • “Docker”是一种协议,“DockerHub”是实现但不限于Docker协议的产品。 Docker API 也由其他提供商实现,例如:
    • GitLab (registry.gitlab.com)
    • GitHub CR (ghcr.io)
    • GCP GCR(gcr.io)
    • AWS ECR(public.ecr.aws 和 .dkr.ecr..amazonaws.com)
    • Azure ACR (.azurecr.io)
  • index.docker.io
    托管 DockerHub 的 Docker 实现。
  • hub.docker.com
    托管丰富的 DockerHub 特定 APIs
  • 注意:DockerHub 实现了通用 Docker HTTP API V2,但它未实现
    _catalog
    来自通用 API 集的 API

为什么我的查询返回“UNAUTHORIZED”错误代码?

为了使用 Docker V2 API,需要为每个调用从

https://auth.docker.io/token
生成 JWT 身份验证令牌,并且该令牌必须在
index.docker.io

处的 DockerHub 调用中用作 Bearer 令牌

当我们像这样点击 DockerHub API 时:

https://index.docker.io/v2/library/alpine/tags/list
,它会返回 401,其中包含有关缺少的飞行前身份验证调用的信息。我们在失败的请求中查找
www-authenticate
响应标头。

例如:

www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/alpine:pull",error="invalid_token"

这意味着,我们需要显式调用以下API来获取auth token。

https://auth.docker.io/token?service=registry.docker.io&scope=repository:library/alpine:pull

https://auth.docker.io/token
无需任何公共存储库授权即可工作。要访问私有存储库,我们需要在请求中添加基本的 http 身份验证。

https://<username>:<password>@auth.docker.io/token?service=registry.docker.io&scope=repository:<repo>:pull

注意:即使请求无效(无效的信用或范围或任何内容),

auth.docker.io
也会生成令牌。为了验证令牌,我们可以解析 JWT(例如:来自 jwt.io)并检查有效负载中的
access
字段,它应该包含请求的范围引用。


10
投票

这是一个从注册表读取存储库的示例程序。我用它作为 Docker Hub 的学习辅助工具。

#!/bin/bash

set -e

# set username and password
UNAME="username"
UPASS="password"

# get token to be able to talk to Docker Hub
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)

# get list of repos for that user account
REPO_LIST=$(curl -s -H "Authorization: JWT ${TOKEN}" 
https://hub.docker.com/v2/repositories/${UNAME}/?page_size=10000 | jq -r '.results|.[]|.name')

# build a list of all images & tags
for i in ${REPO_LIST}
do
  # get tags for repo
  IMAGE_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" 
  https://hub.docker.com/v2/repositories/${UNAME}/${i}/tags/?page_size=10000 | jq -r '.results|.[]|.name')

  # build a list of images from tags
  for j in ${IMAGE_TAGS}
  do
    # add each tag to list
    FULL_IMAGE_LIST="${FULL_IMAGE_LIST} ${UNAME}/${i}:${j}"
  done
done

# output list of all docker images
for i in ${FULL_IMAGE_LIST}
do
  echo ${i}
done

(这来自 Docker 网站上的一篇文章,描述了如何使用 API。)

本质上...

  • 获取代币
  • 将令牌作为标头传递给您进行的任何 API 调用
    Authorization: JWT <token>
  • 您要用于列出存储库的 api 调用是
  • https://hub.docker.com/v2/repositories/<username>/
    
    

3
投票

这个网站说我们不能:(

Dockerhub 托管公共和私有存储库的混合,但不 公开目录端点以编程方式列出它们。


0
投票
我已经修改了

https://stackoverflow.com/a/60549026/7281491,这样我就可以搜索任何其他用户/组织 dockerhub 图像列表:

#!/bin/bash set -e # User to search for UNAME=${1} # Put your own docker hub TOKEN. # You can use pass command or 1password cli to store pat TOKEN=dckr_pat_XXXXXXXXXXXXXXXXXXXXXXXx # get list of namespaces accessible by user (not in use right now) #NAMESPACES=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/namespaces/ | jq -r '.namespaces|.[]') # get list of repos for that user account REPO_LIST=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${UNAME}/?page_size=10000 | jq -r '.results|.[]|.name') # build a list of all images & tags for i in ${REPO_LIST} do # get tags for repo IMAGE_TAGS=$(curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/${UNAME}/${i}/tags/?page_size=10000 | jq -r '.results|.[]|.name') # build a list of images from tags for j in ${IMAGE_TAGS} do # add each tag to list FULL_IMAGE_LIST="${FULL_IMAGE_LIST} ${UNAME}/${i}:${j}" done done # output list of all docker images for i in ${FULL_IMAGE_LIST} do echo ${i} done
输出示例:

gitlab/gitlab-ce:latest gitlab/gitlab-ce:nightly gitlab/gitlab-ce:15.5.9-ce.0 gitlab/gitlab-ce:15.6.6-ce.0 gitlab/gitlab-ce:rc gitlab/gitlab-ce:15.7.5-ce.0 gitlab/gitlab-ce:15.7.3-ce.0 gitlab/gitlab-ce:15.5.7-ce.0 gitlab/gitlab-ce:15.6.4-ce.0 gitlab/gitlab-ce:15.7.2-ce.0 gitlab/gitlab-ce:15.7.1-ce.0 gitlab/gitlab-ce:15.7.0-ce.0 gitlab/gitlab-ce:15.6.3-ce.0 gitlab/gitlab-ce:15.5.6-ce.0 gitlab/gitlab-ce:15.6.2-ce.0 gitlab/gitlab-ce:15.4.6-ce.0 gitlab/gitlab-ce:15.5.5-ce.0 .....
    

0
投票
这是执行相同操作的 Python 代码。这可以访问您的组织和您自己的私人存储库。

旁注,我还有另一堆可以访问清单的代码,但只能在私人/公共用户存储库上,但也不能在组织级别存储库上,有人知道这是为什么吗?

import requests docker_username = "" docker_password = "" docker_organization = "" auth_url = "https://hub.docker.com/v2/users/login/" auth_data = { "username": docker_username, "password": docker_password } auth_response = requests.post(auth_url, json=auth_data) auth_response.raise_for_status() docker_hub_token = auth_response.json()["token"] repositories_list = f"https://hub.docker.com/v2/repositories/{docker_username}/?page_size=100" # repositories_list = f"https://hub.docker.com/v2/repositories/{docker_organization}/?page_size=100" repos_headers = { "Authorization": f"JWT {docker_hub_token}" } repos_response = requests.get(repositories_list, headers=repos_headers) repository_list = repos_response.json()["results"] for repo in repository_list: namespace = repo["namespace"] repo_name = repo["name"] combined_name = f"{namespace}/{repo_name}" print(combined_name)
    
© www.soinside.com 2019 - 2024. All rights reserved.