简体   繁体   English

如何检测docker-py client.build()何时失败

[英]How can I detect when docker-py client.build() fails

I'm using docker-py to build and run Docker images. 我正在使用docker-py构建和运行Docker映像。

From reading the documentation it isn't clear to me how I'm supposed to detect if there was an error building the image. 通过阅读文档 ,我不清楚我应该如何检测构建映像时是否出错。 build() doesn't raise an exception when there's an error. 发生错误时, build()不会引发异常。 That makes me think I have to investigate the responses coming back. 这使我认为我必须调查返回的响应。

What's the best way to determine if docker-py's client.build() fails? 确定docker-py的client.build()是否失败的最佳方法是什么?

It looks like the 'best' way is to decode the response and look for a key named 'error'. 看起来“最佳”方法是解码响应并寻找名为“错误”的密钥。

For example: 例如:

for response in client.build(path, tag, decode=True):
    if response.has_key('error'):
        raise Exception("Error building docker image: {}".format(response['error']))

Create a StreamLineBuilder generator: 创建一个StreamLineBuilder生成器:

import json
class StreamLineBuildGenerator(object):
    def __init__(self, json_data):
        self.__dict__ = json.loads(json_data)

And then use this generator in order to parse your stream: 然后使用此生成器来解析您的流:

import docker
docker_client = docker.Client(version="1.18", base_url="unix:///var/run/docker.sock")

generator = docker_client.build(nocache=False, rm=True, stream=True, tag="my_image_tag", path="my_path")

for line in generator:
    try:
        stream_line = StreamLineBuildGenerator(line)
        if hasattr(stream_line, "error"):
            print(stream_line.error)
            if hasattr(stream_line, "errorDetail"):
                if not stream_line.error == stream_line.errorDetail["message"]:
                    if hasattr(stream_line.errorDetail, "code"):
                        print("[" + stream_line.errorDetail["code"] + "] ", False)
                    print(stream_line.errorDetail["message"])
    except ValueError:
        # If we are not able to deserialize the received line as JSON object, just print it out
        print(line)
        continue

In the spirit of sharing, I want to show an implementation that is a progression of Fabien's answer (which was extremely useful). 本着共享的精神,我想展示一种实现方式,该实现方式是Fabien的回答的扩展(非常有用)。 This does printing, cleanup, et cetera, and throws an informed exception when things are bad: 这样可以进行打印,清理等操作,并在情况不好时抛出一个知情异常:

import json
import logging
import re

import docker

log = logging.getLogger(__name__)


class StreamLineBuildGenerator(object):
    def __init__(self, json_data):
        self.__dict__ = json.loads(json_data)


class Docker(object):
    REGISTRY = "some_docker_registry"

    def __init__(self):
        self.client = docker.from_env()
        self.api_client = docker.APIClient()

    def build(self, path, repository):
        tag = "{}/{}".format(Docker.REGISTRY, repository)
        output = self.api_client.build(path=path, tag=tag)
        self._process_output(output)
        log.info("done building {}".format(repository))

    def push(self, repository):
        tag = "{}/{}".format(Docker.REGISTRY, repository)
        output = self.client.images.push(tag)
        self._process_output(output)
        log.info("done pushing {}".format(tag))

    def _process_output(self, output):
        if type(output) == str:
            output = output.split("\n")

        for line in output:
            if line:
                errors = set()
                try:
                    stream_line = StreamLineBuildGenerator(line)

                    if hasattr(stream_line, "status"):
                        log.info(stream_line.status)

                    elif hasattr(stream_line, "stream"):
                        stream = re.sub("^\n", "", stream_line.stream)
                        stream = re.sub("\n$", "", stream)
                        # found after newline to close (red) "error" blocks: 27 91 48 109
                        stream = re.sub("\n(\x1B\[0m)$", "\\1", stream)
                        if stream:
                            log.info(stream)

                    elif hasattr(stream_line, "aux"):
                        if hasattr(stream_line.aux, "Digest"):
                            log.info("digest: {}".format(stream_line.aux["Digest"]))

                        if hasattr(stream_line.aux, "ID"):
                            log.info("ID: {}".format(stream_line.aux["ID"]))

                    else:
                        log.info("not recognized (1): {}".format(line))

                    if hasattr(stream_line, "error"):
                        errors.add(stream_line.error)

                    if hasattr(stream_line, "errorDetail"):
                        errors.add(stream_line.errorDetail["message"])

                        if hasattr(stream_line.errorDetail, "code"):
                            error_code = stream_line.errorDetail["code"]
                            errors.add("Error code: {}".format(error_code))

                except ValueError as e:
                    log.error("not recognized (2): {}".format(line))

                if errors:
                    message = "problem executing Docker: {}".format(". ".join(errors))
                    raise SystemError(message)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM