Source code for gigl.orchestration.img_builder

import datetime
from pathlib import Path
from typing import Optional

from gigl.common.constants import (
    DOCKER_LATEST_BASE_CPU_IMAGE_NAME_WITH_TAG,
    DOCKER_LATEST_BASE_CUDA_IMAGE_NAME_WITH_TAG,
    DOCKER_LATEST_BASE_DATAFLOW_IMAGE_NAME_WITH_TAG,
)
from gigl.common.logger import Logger
from gigl.common.utils.os_utils import run_command_and_stream_stdout

[docs] logger = Logger()
[docs] CUSTOMER_SRC_DOCKERFILE_PATH = ( Path(__file__).parent.resolve() / "Dockerfile.customer_src" ).as_posix()
[docs] def build_and_push_customer_src_images( context_path: str, export_docker_artifact_registry: str, base_image_cuda: str = DOCKER_LATEST_BASE_CUDA_IMAGE_NAME_WITH_TAG, base_image_cpu: str = DOCKER_LATEST_BASE_CPU_IMAGE_NAME_WITH_TAG, base_image_dataflow: str = DOCKER_LATEST_BASE_DATAFLOW_IMAGE_NAME_WITH_TAG, ) -> tuple[str, str, str]: """ Package user provided code located at context_path into docker images based on the base images provided. The images are pushed to the export_docker_artifact_registry. Args: context_path (str): Root directory that will be copied into the docker images. export_docker_artifact_registry (str): Docker artifact registry to push the images to. base_image_cuda (str): Base image to use for the CUDA image. base_image_cpu (str): Base image to use for the CPU image. base_image_dataflow (str): Base image to use for the Dataflow image. Returns: tuple[str, str, str]: The names of cuda, cpu, and dataflow images. """ logger.info( f"Building and pushing customer src images to {export_docker_artifact_registry}" ) logger.info( f"Using base images: {base_image_cuda}, {base_image_cpu}, {base_image_dataflow}" ) logger.info(f"Using context path: {context_path}") tag = f"{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}" export_cuda_image_name = f"{export_docker_artifact_registry}/src-cuda:{tag}" export_cpu_image_name = f"{export_docker_artifact_registry}/src-cpu:{tag}" export_dataflow_image_name = ( f"{export_docker_artifact_registry}/src-cpu-dataflow:{tag}" ) logger.info(f"Building and pushing cuda image to {export_cuda_image_name}") build_and_push_image( base_image=base_image_cuda, image_name=export_cuda_image_name, dockerfile_path=CUSTOMER_SRC_DOCKERFILE_PATH, context_path=context_path, ) logger.info(f"Building and pushing cpu image to {export_cpu_image_name}") build_and_push_image( base_image=base_image_cpu, image_name=export_cpu_image_name, dockerfile_path=CUSTOMER_SRC_DOCKERFILE_PATH, context_path=context_path, ) logger.info(f"Building and pushing dataflow image to {export_dataflow_image_name}") build_and_push_image( base_image=base_image_dataflow, image_name=export_dataflow_image_name, dockerfile_path=CUSTOMER_SRC_DOCKERFILE_PATH, context_path=context_path, ) logger.info(f"Done building and pushing customer src images") return export_cuda_image_name, export_cpu_image_name, export_dataflow_image_name
[docs] def build_and_push_image( base_image: Optional[str], image_name: str, dockerfile_path: str, context_path: str, multi_arch: bool = False, ) -> None: """ Builds and pushes a Docker image. Args: base_image (Optional[str]): The base image to use for the build. image_name (str): The name of the Docker image to build and push. dockerfile_path (str): The path to the Dockerfile to use for the build. context_path (str): The path to the context to use for the build. multi_arch (bool): Whether to build a multi-architecture Docker image. Defaults to False. """ if multi_arch: build_command = [ "docker", "buildx", "build", "--platform", "linux/amd64,linux/arm64", "-f", str(dockerfile_path), "-t", image_name, "--push", ] else: build_command = [ "docker", "build", "-f", str(dockerfile_path), "-t", image_name, ] if base_image: build_command.extend(["--build-arg", f"BASE_IMAGE={base_image}"]) build_command.append(context_path) logger.info(f"Running command: {' '.join(build_command)}") returncode = run_command_and_stream_stdout(" ".join(build_command)) if returncode != 0: logger.error(f"Command failed: {' '.join(build_command)}") raise RuntimeError(f"Docker build failed with exit code {returncode}") # Push image if it's not a multi-arch build (multi-arch images are pushed in the build step) if not multi_arch: push_command = ["docker", "push", image_name] returncode = run_command_and_stream_stdout(" ".join(push_command)) if returncode != 0: logger.error(f"Command failed: {' '.join(push_command)}") raise RuntimeError(f"Docker push failed with exit code {returncode}")