本文最后编辑于 前,其中的内容可能需要更新。
背景
来自一个奇奇怪怪的需求,要将一些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)
|