Docker CLI 允许标记,但 Docker Python API 引发 API 错误
Docker CLI allows tag, but Docker Python API raises APIError
我正在尝试使用 Docker Python API 将本地 Docker 图像推送到 ECR。作为该过程的一部分,我需要以某种方式标记图像。当我在 CLI 上这样做时,它起作用了:
docker tag foo/bar '{user_id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar'
然而,当我尝试使用 Docker Python SDK 中的 docker.images.Image.tag
函数做同样的事情时,它失败了:
import docker
(docker.client.from_env().images.get('foo/bar')
.tag('foo/bar',
'{user-id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar'
)
)
(将上面代码示例中的 user_id
替换为 AWS 用户 ID 值,例如 717171717171
;出于这个问题的目的,我在此处对其进行了混淆处理)
出现以下错误:
In [10]: docker.client.from_env().images.get('foo/bar').ta
...: g('foo/bar', '{user_id}.dkr.ecr.us-east-1.amaz
...: onaws.com/foo/bar')
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/api/client.py in _raise_for_status(self, response)
255 try:
--> 256 response.raise_for_status()
257 except requests.exceptions.HTTPError as e:
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/requests/models.py in raise_for_status(self)
939 if http_error_msg:
--> 940 raise HTTPError(http_error_msg, response=self)
941
HTTPError: 500 Server Error: Internal Server Error for url: http+docker://localhost/v1.35/images/sha256:afe07035bce72b6c496878a7e3960bedffd46c1bedc79f1bd2b89619e8457194/tag?tag={user_id}.dkr.ecr.us-east-1.amazonaws.com%2Ffoo%2Fbar&repo=foo%2Fbar&force=0
During handling of the above exception, another exception occurred:
APIError Traceback (most recent call last)
<ipython-input-10-5bb015d17409> in <module>
----> 1 docker.client.from_env().images.get('alekseylearn-example/build').tag('foo/bar', '{user_id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar')
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/models/images.py in tag(self, repository, tag, **kwargs)
120 (bool): ``True`` if successful
121 """
--> 122 return self.client.api.tag(self.id, repository, tag=tag, **kwargs)
123
124
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/utils/decorators.py in wrapped(self, resource_id, *args, **kwargs)
17 'Resource ID was not provided'
18 )
---> 19 return f(self, resource_id, *args, **kwargs)
20 return wrapped
21 return decorator
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/api/image.py in tag(self, image, repository, tag, force)
531 url = self._url("/images/{0}/tag", image)
532 res = self._post(url, params=params)
--> 533 self._raise_for_status(res)
534 return res.status_code == 201
535
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/api/client.py in _raise_for_status(self, response)
256 response.raise_for_status()
257 except requests.exceptions.HTTPError as e:
--> 258 raise create_api_error_from_http_exception(e)
259
260 def _result(self, response, json=False, binary=False):
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/errors.py in create_api_error_from_http_exception(e)
29 else:
30 cls = NotFound
---> 31 raise cls(e, response=response, explanation=explanation)
32
33
APIError: 500 Server Error: Internal Server Error ("invalid tag format")
为什么CLI命令成功而Python API命令失败?
在详细的 Docker API 术语中,像 123456789012.dkr.ecr.us-east-1.amazon.aws.com/foo/bar:baz
这样的图像名称被分成 repository(在冒号之前)和a tag(冒号后)。存储库名称的主机名部分是 注册表 。如果指定 none,则默认标记值是文字 latest
.
在你的例子中,你已经有了一个 Image
对象,所以你需要应用第二个参数的两个 "halves":
docker.client.from_env().images.get('foo/bar')
.tag('{user-id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar',
'latest'
)
(在许多实际情况下,使用 latest
标签并不是一个好主意;时间戳或源代码控制提交 ID 之类的东西可以更好地识别图像并有助于向 ECS 或 EKS 或普通 Kubernetes 等服务指示他们需要进行更新。此外,虽然 ECR 图像 ID 有点长得不切实际,但在脚本上下文中没有什么能阻止您直接使用它们;例如,您可以 docker build -t 12345...amazonaws.com/foo/bar:abcdef0
并跳过中间 docker tag
如果你愿意,请走一步。)
我正在尝试使用 Docker Python API 将本地 Docker 图像推送到 ECR。作为该过程的一部分,我需要以某种方式标记图像。当我在 CLI 上这样做时,它起作用了:
docker tag foo/bar '{user_id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar'
然而,当我尝试使用 Docker Python SDK 中的 docker.images.Image.tag
函数做同样的事情时,它失败了:
import docker
(docker.client.from_env().images.get('foo/bar')
.tag('foo/bar',
'{user-id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar'
)
)
(将上面代码示例中的 user_id
替换为 AWS 用户 ID 值,例如 717171717171
;出于这个问题的目的,我在此处对其进行了混淆处理)
出现以下错误:
In [10]: docker.client.from_env().images.get('foo/bar').ta
...: g('foo/bar', '{user_id}.dkr.ecr.us-east-1.amaz
...: onaws.com/foo/bar')
---------------------------------------------------------------------------
HTTPError Traceback (most recent call last)
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/api/client.py in _raise_for_status(self, response)
255 try:
--> 256 response.raise_for_status()
257 except requests.exceptions.HTTPError as e:
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/requests/models.py in raise_for_status(self)
939 if http_error_msg:
--> 940 raise HTTPError(http_error_msg, response=self)
941
HTTPError: 500 Server Error: Internal Server Error for url: http+docker://localhost/v1.35/images/sha256:afe07035bce72b6c496878a7e3960bedffd46c1bedc79f1bd2b89619e8457194/tag?tag={user_id}.dkr.ecr.us-east-1.amazonaws.com%2Ffoo%2Fbar&repo=foo%2Fbar&force=0
During handling of the above exception, another exception occurred:
APIError Traceback (most recent call last)
<ipython-input-10-5bb015d17409> in <module>
----> 1 docker.client.from_env().images.get('alekseylearn-example/build').tag('foo/bar', '{user_id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar')
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/models/images.py in tag(self, repository, tag, **kwargs)
120 (bool): ``True`` if successful
121 """
--> 122 return self.client.api.tag(self.id, repository, tag=tag, **kwargs)
123
124
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/utils/decorators.py in wrapped(self, resource_id, *args, **kwargs)
17 'Resource ID was not provided'
18 )
---> 19 return f(self, resource_id, *args, **kwargs)
20 return wrapped
21 return decorator
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/api/image.py in tag(self, image, repository, tag, force)
531 url = self._url("/images/{0}/tag", image)
532 res = self._post(url, params=params)
--> 533 self._raise_for_status(res)
534 return res.status_code == 201
535
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/api/client.py in _raise_for_status(self, response)
256 response.raise_for_status()
257 except requests.exceptions.HTTPError as e:
--> 258 raise create_api_error_from_http_exception(e)
259
260 def _result(self, response, json=False, binary=False):
~/miniconda3/envs/alekseylearn-dev/lib/python3.6/site-packages/docker/errors.py in create_api_error_from_http_exception(e)
29 else:
30 cls = NotFound
---> 31 raise cls(e, response=response, explanation=explanation)
32
33
APIError: 500 Server Error: Internal Server Error ("invalid tag format")
为什么CLI命令成功而Python API命令失败?
在详细的 Docker API 术语中,像 123456789012.dkr.ecr.us-east-1.amazon.aws.com/foo/bar:baz
这样的图像名称被分成 repository(在冒号之前)和a tag(冒号后)。存储库名称的主机名部分是 注册表 。如果指定 none,则默认标记值是文字 latest
.
在你的例子中,你已经有了一个 Image
对象,所以你需要应用第二个参数的两个 "halves":
docker.client.from_env().images.get('foo/bar')
.tag('{user-id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar',
'latest'
)
(在许多实际情况下,使用 latest
标签并不是一个好主意;时间戳或源代码控制提交 ID 之类的东西可以更好地识别图像并有助于向 ECS 或 EKS 或普通 Kubernetes 等服务指示他们需要进行更新。此外,虽然 ECR 图像 ID 有点长得不切实际,但在脚本上下文中没有什么能阻止您直接使用它们;例如,您可以 docker build -t 12345...amazonaws.com/foo/bar:abcdef0
并跳过中间 docker tag
如果你愿意,请走一步。)