本文最后编辑于  前,其中的内容可能需要更新。
                
                
                    
                
                
                背景
来自一个奇奇怪怪的需求,要将一些changelog放在镜像的label中,姑且简单实现一下。
获取docker token
ps: 最简单的token获取方式,从.docker/config.json中拷贝。
开玩笑,需要docker token 可以使用如下命令生成
1
   | echo -n "$USERNAME:PASSWORD" | base64
   | 
 
获取认证地址相关信息
docker的客户端登陆使用的是比较简单的basic auth,简单发送请求获取Basic realm中提供的信息,他提供了docker认证地址和仓库的地址以及你申请的动作(pull,push 等)
1 2 3 4 5
   | auth_headers = {'Authorization': f'Basic {auth_token}', 'User-Agent': 'Docker-Client/19.03.2 (linux)'}  first_header = {"X-Docker-Token": "true"}  s = requests.get(registry_url, headers=first_header)    parsed = www_authenticate.parse(s.headers['www-authenticate'])
  | 
 
构造新的请求来获取token
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | auth_headers = {'Authorization': f'Basic {auth_token}', 'User-Agent': 'Docker-Client/19.03.2 (linux)'}          	if 'bearer' in parsed:          info = parsed['bearer']          scope = 'repository:' + f'{namespace}/{repo}' + ':' + ',*'                url_parts = list(urlparse.urlparse(info['realm']))      query = urlparse.parse_qs(url_parts[4])      query.update({          'service': info['service'],          'scope': scope                  })      url_parts[4] = urlencode(query, True)      url_parts[0] = 'https'      auth_url = urlparse.urlunparse(url_parts)            token = f"Bearer {requests.get(auth_url,headers=auth_headers).json()['token']}"
  | 
 
使用token来获取config信息
1 2 3 4 5 6 7
   | new_header = {'Authorization': token, 'Accept': 'application/vnd.docker.distribution.manifest.v2+json'}                  metadata = requests.get(f"{registry_url}/{namespace}/{repo}/manifests/{tag}", headers=new_header)         conf_digest = metadata.json()['config']['digest']         label = requests.get(f"{registry_url}/{namespace}/{repo}/blobs/{conf_digest}", headers=new_header).json()         msg = label['config']['Labels'][label]         return msg
  | 
 
    
    
        1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
   | import requests import www_authenticate import urllib.parse as urlparse from urllib.parse import urlencode """ 本部分用于从镜像仓库获取镜像的提交信息。 提交信息通过docker镜像的label来加入镜像 调用Registry v2的api实现 参考链接: https://docs.docker.com/registry/spec/api/ """
  auth_token = $YOUR_REGISTRY_URL registry_url = $YOUR_AUTH_TOKEN
 
 
  def get_commit_msg(namespace, repo, tag,label):     try:         auth_headers = {'Authorization': f'Basic {auth_token}', 'User-Agent': 'Docker-Client/19.03.2 (linux)'}         first_header = {"X-Docker-Token": "true"}         s = requests.get(registry_url, headers=first_header)                  parsed = www_authenticate.parse(s.headers['www-authenticate'])         if 'bearer' in parsed:             info = parsed['bearer']             scope = 'repository:' + f'{namespace}/{repo}' + ':' + ',*'                      url_parts = list(urlparse.urlparse(info['realm']))         query = urlparse.parse_qs(url_parts[4])         query.update({             'service': info['service'],             'scope': scope                     })         url_parts[4] = urlencode(query, True)         url_parts[0] = 'https'         auth_url = urlparse.urlunparse(url_parts)                  token = f"Bearer {requests.get(auth_url,headers=auth_headers).json()['token']}"                  new_header = {'Authorization': token, 'Accept': 'application/vnd.docker.distribution.manifest.v2+json'}                  metadata = requests.get(f"{registry_url}/{namespace}/{repo}/manifests/{tag}", headers=new_header)         conf_digest = metadata.json()['config']['digest']         label = requests.get(f"{registry_url}/{namespace}/{repo}/blobs/{conf_digest}", headers=new_header).json()         msg = label['config']['Labels'][label]         return msg     except Exception as e:         print(e) 
   |