Exemple #1
0
    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
Exemple #2
0
    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
Exemple #3
0
    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