def build_docker_image()

in cli/src/klio_cli/utils/docker_utils.py [0:0]


def build_docker_image(job_dir, image_name, image_tag, config_file=None):
    """Build given Docker image.

    Note: This uses the python Docker SDK's low-level API in order to capture
    and emit build logs as they are generated by Docker. Using the
    high-level API, you only get access to logs at the end of the build,
    which creates a bad user experience.

    Args:
        job_dir (str): Relative path to directory containing Dockerfile.
        image_name (str): Name to build the image with (forms a ‘name:tag’ pair)
        image_tag (str): Tag to build the image with (forms a ‘name:tag’ pair)
    Raises:
        SystemExit(1) If Docker build errors out, process terminates.
    """

    def clean_logs(log_generator):
        # Loop through lines containing log JSON objects.
        # Example line: {"stream":"Starting build..."}\r\n{"stream":"\\n"}\n
        for line in log_generator:
            if isinstance(line, bytes):
                line = line.decode("utf-8")
            # Some lines contain multiple whitespace-separated objects.
            # Split them so json.loads doesn't choke.
            for log_obj in line.split("\r\n"):
                # Some log objects only wrap newlines.
                # Split sometimes produces '' char.
                # Remove these artifacts.
                if log_obj != '{"stream":"\\n"}' and log_obj != "":
                    yield log_obj

    def print_log(log):
        if "stream" in log:
            logging.info(log["stream"].strip("\n"))
        if "error" in log:
            fail_color = "\033[91m"
            end_color = "\033[0m"
            logging.info(
                "{}{}{}".format(
                    fail_color, log["errorDetail"]["message"], end_color
                )
            )
            logging.error("\nDocker hit an error while building job image.")
            logging.error(
                "Please fix your Dockerfile: {}/Dockerfile".format(job_dir)
            )
            raise SystemExit(1)

    build_flag = {
        "path": job_dir,
        "tag": "{}:{}".format(image_name, image_tag),
        "rm": True,
        "buildargs": {
            "tag": image_tag,
            "KLIO_CONFIG": config_file or "klio-job.yaml",
        },
    }  # Remove intermediate build containers.
    logs = docker.APIClient(base_url="unix://var/run/docker.sock").build(
        **build_flag
    )

    for log_obj in clean_logs(logs):
        log = json.loads(log_obj)
        print_log(log)