【问题标题】:Docker Python API - Tagging ContainersDocker Python API - 标记容器
【发布时间】:2018-02-01 00:48:28
【问题描述】:

我将 Docker 与 AWS ECR 存储库一起使用。他们指示您执行的步骤之一是运行“docker tag”以使用标签标记构建的图像,该标签包含图像将存储在 ECR 中的“完全合格”位置。

我正在将我必须的脚本迁移到 Python API(而不是对 docker 客户端进行 shell 调用)。我无法在https://docker-py.readthedocs.io/en/stable/images.html 的 API 文档中找到“docker tag”的等效项。

有人可以指出正确的方向吗?

【问题讨论】:

  • 使用low-level API:https://docker-py.readthedocs.io/en/stable/api.html#module-docker.api.image 有一个tag() 方法。

标签: python api docker tags


【解决方案1】:

这个回答对我帮助很大,谢谢!

在开发流程时,我被 docker-py 页面上的术语弄糊涂了,我认为这会受益于更多示例。

我在开发过程中不确定我是否正确构建,或者我是否遇到了身份验证或授权问题。

我需要使用 Docker CLI 仔细监控我的构建结果,并捕获和分析来自不同构建、标记和推送功能的输出。

从这些函数获取输出的另一个警告是明确说明 docker-py pull() 函数而不是其他函数的警告:如果您要求该函数为操作的输出提供生成器,则必须使用该生成器发电机。我能够让我的流程以调试级别的详细程度工作。

不幸的是,当我关闭代码中的详细信息并且没有使用 build() 和 push() 的生成器(tag() 只有布尔结果)时,我的流程只出现了工作:它没有抛出错误,但也没有构建或推送代码!如果您未处于调试模式,最好不要打开流输出,或者保持打开状态并使用deque() 来使用输出而不进行处理。

总结标签使用方式的差异:

  • build() 采用“本地标签”,它只是构建的名称,例如'myproj'
  • tag() 将“版本标签”应用于您刚刚使用build() 构建的“本地标签”,版本标签将包括注册表和版本标签,例如,myregistry.mydomain.com/myname/myproj:latest
  • push() 会将“版本标签”中的图像推送到版本标签中指定的注册表。所以在这种情况下,您标记为myregistry.mydomain.com/myname/myproj:latest 的图像将被推送到注册表myregistry.mydomain.com。

【讨论】:

    【解决方案2】:

    对于那些在 AWS 中使用 ECR/ECS 的人,这里有一个示例来说明如何进行此操作。

    亚马逊在 ECR 中提供这样的指令来推送您的图片:

    aws ecr get-login --no-include-email --region us-west-2
    docker build -t myproj .
    docker tag calclab:latest XXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/myproj:latest
    docker push XXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/myproj:latest
    

    这是使用 Docker Python API 和 Boto(AWS 的 Python 库)的粗略等价物。它包括在 ECR 中标记图像两次,这样我就可以在跟踪最新版本的同时跟踪每个图像的版本号(所以我的 ECS 任务可以默认情况下总是抓取最新的图像)

    import docker
    import boto3
    
    def ecrDemo(version_number):
    
        # The ECR Repository URI
        repo = XXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/myproj
        # The name of the [profile] stored in .aws/credentials
        profile = "sandbox"
        # The region your ECR repo is in
        region = "us-west-2"
        # How you want to tag your project locally
        local_tag = "myproj"
    
        #Set up a session
        session = boto3.Session(profile_name=profile, region_name=region)
        ecr = session.client('ecr')
    
        docker_api = docker.APIClient()
    
        print "Building image " + local_tag
        for line in docker_api.build(path='.', tag=local_tag, stream=True, \
            dockerfile='./Dockerfile.myproj'):
            process_docker_api_line(line)
    
        # Make auth call and parse out results
        auth = ecr.get_authorization_token()
        token = auth["authorizationData"][0]["authorizationToken"]
        username, password = b64decode(token).split(':')
        endpoint = auth["authorizationData"][0]["proxyEndpoint"]
    
        # print "Make authentication call"
        # docker_api.login(username=user, password=password, \
        #             registry=endpoint, reauth=True)
        auth_config_payload = {'username': username, 'password': password}
    
    
    
        version_tag = repo + ':latest'
        latest_tag = repo + ':' + version_number
    
        print "Tagging version " + version_tag
        if docker_api.tag(local_tag, version_tag) is False:
            raise RuntimeError("Tag appeared to fail: " + version_tag)
    
        print "Tagging latest " + latest_tag
        if docker_api.tag(local_tag, latest_tag) is False:
            raise RuntimeError("Tag appeared to fail: " + tag_latest)
    
        print "Pushing to repo " + version_tag
        for line in docker_api.push(version_tag, stream=True, auth_config=auth_config_payload):
            self.process_docker_api_line(line)
    
        print "Pushing to repo " + latest_tag
        for line in docker_api.push(latest_tag, stream=True, auth_config=auth_config_payload):
            self.process_docker_api_line(line)
    
        print "Removing taged deployment images"
        # You will still have the local_tag image if you need to troubleshoot
        docker_api.remove_image(version_tag, force=True)
        docker_api.remove_image(latest_tag, force=True)
    
    def process_docker_api_line(payload):
        """ Process the output from API stream, throw an Exception if there is an error """
        # Sometimes Docker sends to "{}\n" blocks together...
        for segment in payload.split('\n'):
            line = segment.strip()
            if line:
                try:
                    line_payload = json.loads(line)
                except ValueError as ex:
                    print "Could not decipher payload from API: " + ex.message
                if line_payload:
                    if "errorDetail" in line_payload:
                        error = line_payload["errorDetail"]
                        sys.stderr.write(error["message"])
                        raise RuntimeError("Error on build - code " + `error["code"]`)
                    elif "stream" in line_payload:
                        sys.stdout.write(line_payload["stream"])
    

    【讨论】:

    • 这很好,我正要发布一个问题(如果需要的话我会发布)但我需要使用 API 从 AWS ECR 拉/推图像,所以我不能使用经典的 docker login 我将使用这里发布的方法。如果您有开箱即用的示例,那就太好了,或者只是命令或 API 名称可以为我省去很多麻烦。
    • 您好,除了上面的函数包含构建并且不包含您的项目的 repo 或您的凭据这一事实之外,您还需要哪些其他信息?
    • 嘿,Jason,就像我说的那样,这很棒,给了我一个很大的开端(明天开始工作..)我需要做的是从 AWS ECR 中提取图像,重新标记它并将其推送到另一个 ECR(可能是另一个区域或帐户)。我想我错过了上面代码中的 pull 命令
    • 您可以使用docker-py.readthedocs.io/en/stable/… 中记录的“pull”命令。 1. 从配置了源区域的会话中获取身份验证令牌,构建身份验证配置有效负载 2. 使用 pull 命令从 ECR 检索源映像,包括 auth_config 3. 使用“tag”命令重新标记您拉取的源映像 4 . 从配置了目标区域的第二个会话中获取身份验证令牌,构建身份验证配置有效负载 5. 推送 如果您遇到困难,请发布您正在进行的内容,我会尽我所能提供帮助
    • 是的,我已经在那里了。我要为您的解决方案 +1 只是因为它给了我如此巨大的推动力,而且我的解决方案几乎与您所说的完全相同。我正在努力解决的一个区别(我想这超出了本次对话的范围)是如何与 ECR“通信”,现在我在 AWS 上有一个 ECR 主机,我通过 ssh 连接并执行命令,我'现在正在考虑在主机上安装 AWS 代理并使用 boto3 .. 只是共享以防万一有人有类似的东西并需要帮助。感谢所有的帮助杰森!!!
    【解决方案3】:

    这些是您可以用来构建和标记图像的步骤。

    import docker
    tag = 'latest' # or whatever you want
    client = docker.from_env()
    # identifier of the image on your system
    dockername = "%s:%s" % (<name of the image on your system>, <tag>)
    # the target identifier
    target = "%s:%d/%s" % (<registry address>, <registry_port>, <id or name of the image>)
    
    # the url is usually unix://var/run/docker.sock' but depends on your environment
    cli = docker.APIClient(base_url=<the daemon\'s url or socket>)
    # build the image
    cli.build(path=..., tag=dockername, pull=..., buildargs=...)
    # tag it
    image = client.images.get(dockername)
    image.tag(target, tag=tag)
    

    【讨论】:

    • 谢谢!毫无疑问,低级 API 是使用这个库的方式。我还受益于能够监控诸如构建之类的进度。
    猜你喜欢
    • 1970-01-01
    • 2019-05-08
    • 2019-06-06
    • 2020-02-29
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多