Docker CLI разрешает тег, но Docker Python API вызывает APIError

Я пытаюсь вставить локальный образ Docker в ECR с помощью Docker Python API. В рамках этого процесса мне нужно пометить изображение определенным образом. Когда я делаю это на CLI, это работает:

docker tag foo/bar '{user_id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar'

Однако, когда я пытаюсь сделать то же самое, используя docker.images.Image.tag Функция в Docker Python SDK не работает:

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, например 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 терпит неудачу?

1 ответ

Решение

В подробном жаргоне Docker API, имя изображения, как 123456789012.dkr.ecr.us-east-1.amazon.aws.com/foo/bar:baz делится на репозиторий (перед двоеточием) и тег (после двоеточия). Часть имени хоста имени хранилища является реестром. Значение тега по умолчанию, если ничего не указано, является литералом latest,

В вашем случае у вас уже есть Image объект, поэтому вам нужно применить две "половинки" второго аргумента:

docker.client.from_env().images.get('foo/bar')
 .tag('{user-id}.dkr.ecr.us-east-1.amazonaws.com/foo/bar',
      'latest'
     )

(Во многих практических случаях использование latest тег не очень хорошая идея; что-то вроде временной метки или идентификатора коммита контроля источника лучше идентифицирует изображение и помогает указывать таким службам, как ECS или EKS или обычным Kubernetes, что им необходимо сделать обновление. Кроме того, хотя идентификаторы изображений ECR непрактично длинные, в контексте сценариев ничто не мешает вам использовать их напрямую; Вы можете, например, docker build -t 12345...amazonaws.com/foo/bar:abcdef0 и пропустить промежуточный docker tag шаг, если хотите.)

Другие вопросы по тегам