def build_image(self, push: bool = True) -> tuple: """ Build a Docker image using the docker python library. Args: - push (bool, optional): Whether or not to push the built Docker image, this requires the `registry_url` to be set Returns: - tuple: generated UUID strings `image_name`, `image_tag` Raises: - InterruptedError: if either pushing or pulling the image fails """ image_name = self.image_name or str(uuid.uuid4()) image_tag = self.image_tag or str(uuid.uuid4()) # Make temporary directory to hold serialized flow, healthcheck script, and dockerfile with tempfile.TemporaryDirectory() as tempdir: # Build the dockerfile if self.base_image and not self.local_image: self.pull_image() self.create_dockerfile_object(directory=tempdir) client = docker.APIClient(base_url=self.base_url, version="auto") # Verify that a registry url has been provided for images that should be pushed if self.registry_url: full_name = os.path.join(self.registry_url, image_name) elif push is True: raise ValueError( "This environment has no `registry_url`, and cannot be pushed." ) else: full_name = image_name # Use the docker client to build the image logging.info("Building the flow's Docker storage...") output = client.build( path=tempdir, tag="{}:{}".format(full_name, image_tag), forcerm=True ) self._parse_generator_output(output) if len(client.images(name=full_name)) == 0: raise SerializationError( "Your flow failed to deserialize in the container; please ensure that all necessary files and dependencies have been included." ) # Push the image if requested if push: self.push_image(full_name, image_tag) # Remove the image locally after being pushed client.remove_image( image="{}:{}".format(full_name, image_tag), force=True ) return image_name, image_tag
def build_image(self, flow: "prefect.Flow", push: bool = True) -> tuple: """ Build the Docker image using the docker python library. Optionally pushes the image if both `push`=`True` and `self.registry_url` is set. Args: - flow (prefect.Flow): Flow to be placed the image - push (bool): Whether or not to push to registry after build Returns: - tuple: `image_name`, `image_tag` (strings) """ image_name = str(uuid.uuid4()) image_tag = str(uuid.uuid4()) with tempfile.TemporaryDirectory() as tempdir: self.pull_image() self.create_dockerfile(flow=flow, directory=tempdir) client = docker.APIClient(base_url="unix://var/run/docker.sock") if self.registry_url: full_name = os.path.join(self.registry_url, image_name) elif push is True: raise ValueError( "This environment has no `registry_url`, and cannot be pushed." ) else: full_name = image_name logging.info("Building the flow's container environment...") output = client.build( path=tempdir, tag="{}:{}".format(full_name, image_tag), forcerm=True ) self._parse_generator_output(output) if len(client.images(name=full_name)) == 0: raise SerializationError( "Your flow failed to deserialize in the container; please ensure that all necessary files and dependencies have been included." ) if push: self.push_image(full_name, image_tag) # Remove the image locally after being pushed client.remove_image( image="{}:{}".format(full_name, image_tag), force=True ) return image_name, image_tag
def _build_image(self, push: bool = True) -> tuple: """ Build a Docker image using the docker python library. Args: - push (bool, optional): Whether or not to push the built Docker image, this requires the `registry_url` to be set Returns: - tuple: generated UUID strings `image_name`, `image_tag` Raises: - InterruptedError: if either pushing or pulling the image fails """ assert isinstance(self.image_name, str), "Image name must be provided" assert isinstance(self.image_tag, str), "An image tag must be provided" # Make temporary directory to hold serialized flow, healthcheck script, and dockerfile with tempfile.TemporaryDirectory() as tempdir: # Build the dockerfile if self.base_image and not self.local_image: self.pull_image() self.create_dockerfile_object(directory=tempdir) client = docker.APIClient(base_url=self.base_url, version="auto") # Verify that a registry url has been provided for images that should be pushed if self.registry_url: full_name = str( PurePosixPath(self.registry_url, self.image_name)) elif push is True: warnings.warn( "This Docker storage object has no `registry_url`, and will not be pushed.", UserWarning, ) full_name = self.image_name else: full_name = self.image_name # Use the docker client to build the image logging.info("Building the flow's Docker storage...") output = client.build( path=tempdir, tag="{}:{}".format(full_name, self.image_tag), forcerm=True, ) self._parse_generator_output(output) if len(client.images(name=full_name)) == 0: raise SerializationError( "Your flow failed one of its deployment health checks! Please ensure that all necessary files and dependencies have been included." ) # Push the image if requested if push and self.registry_url: self.push_image(full_name, self.image_tag) # Remove the image locally after being pushed client.remove_image(image="{}:{}".format( full_name, self.image_tag), force=True) return self.image_name, self.image_tag