def get_or_build_image(self, name: str, tag: str, dockerfile: Union[str, Callable[..., str]], *,
                           pull=True, build_context: Optional[Path]=None):
        """
        A proxy for commonly built images, returns them from the local system if they exist, tries to pull them if
        pull isn't disabled, otherwise builds them by the definition in ``dockerfile``.

        :param name: Name of the image
        :param tag: Image tag
        :param dockerfile: Dockerfile text or a callable (no arguments) that produces Dockerfile text
        :param pull: If the image is not present locally, allow pulling from registry (default is ``True``)
        :param build_context: A path to a folder. If it's provided, docker will build the image in the context
            of this folder. (eg. if ``ADD`` is needed)
        """
        if self.image_exists(name, tag):
            logger.info("Image %s:%s exists", name, tag)
            return

        elif pull:
            logger.info("Trying to pull image %s:%s", name, tag)

            try:
                self.client.images.pull(name, tag=tag)
                logger.info("The image %s:%s was pulled from registry", name, tag)
                return
            except docker.errors.APIError:
                logger.info("The image %s:%s can't be pulled, building locally.", name, tag)

        if callable(dockerfile):
            dockerfile = dockerfile()

        try:
            if build_context is None:
                fileobj = BytesIO(bytes(dockerfile, "utf-8"))  # required by the docker library

                self.client.images.build(
                    fileobj=fileobj,
                    tag=f"{name}:{tag}"
                )
            else:
                dockerfile_file = build_context / "dockerfile"
                dockerfile_file.write_text(dockerfile)

                self.client.images.build(
                    path=str(build_context.resolve()),
                    dockerfile=dockerfile_file.name,
                    tag=f"{name}:{tag}"
                )

                dockerfile_file.unlink()
        except docker.errors.BuildError as e:
            for line in e.build_log:
                if isinstance(line, dict) and line.get("errorDetail") and line["errorDetail"].get("code") in {124, 143}:
                    raise BuildTimeoutError(f"Installing of requirements timeouted after "
                                            f"{self.requirements_timeout} seconds.")

            logger.exception(e)

            raise BuildError("Building docker image failed, see extra info for details.", extra_info={
                "build_log": e.build_log
            })
def get_or_build_image ( self , name : str , tag : str , dockerfile : Union [ str , Callable [ ... , str ] ] , * , pull = True , build_context : Optional [ Path ] = None ) : if self . image_exists ( name , tag ) : logger . info ( "Image %s:%s exists" , name , tag ) return elif pull : logger . info ( "Trying to pull image %s:%s" , name , tag ) try : self . client . images . pull ( name , tag = tag ) logger . info ( "The image %s:%s was pulled from registry" , name , tag ) return except docker . errors . APIError : logger . info ( "The image %s:%s can't be pulled, building locally." , name , tag ) if callable ( dockerfile ) : dockerfile = dockerfile ( ) try : if build_context is None : fileobj = BytesIO ( bytes ( dockerfile , "utf-8" ) ) self . client . images . build ( fileobj = fileobj , tag = f"{name}:{tag}" ) else : dockerfile_file = build_context / "dockerfile" dockerfile_file . write_text ( dockerfile ) self . client . images . build ( path = str ( build_context . resolve ( ) ) , dockerfile = dockerfile_file . name , tag = f"{name}:{tag}" ) dockerfile_file . unlink ( ) except docker . errors . BuildError as e : for line in e . build_log : if isinstance ( line , dict ) and line . get ( "errorDetail" ) and line [ "errorDetail" ] . get ( "code" ) in { 124 , 143 } : raise BuildTimeoutError ( f"Installing of requirements timeouted after " f"{self.requirements_timeout} seconds." ) logger . exception ( e ) raise BuildError ( "Building docker image failed, see extra info for details." , extra_info = { "build_log" : e . build_log } )
A proxy for commonly built images, returns them from the local system if they exist, tries to pull them if
        pull isn't disabled, otherwise builds them by the definition in ``dockerfile``.

        :param name: Name of the image
        :param tag: Image tag
        :param dockerfile: Dockerfile text or a callable (no arguments) that produces Dockerfile text
        :param pull: If the image is not present locally, allow pulling from registry (default is ``True``)
        :param build_context: A path to a folder. If it's provided, docker will build the image in the context
            of this folder. (eg. if ``ADD`` is needed)