code: def _build_docker_image(
      image_name: str,
      py_version: str,
      image_type: str,
      suffix: Optional[str] = None,
      no_cache=True,
  ):
      """Builds Docker image with the provided info.
  
      image_name: The name of the image to build. Must be one of
          IMAGE_NAMES.
      py_version: The Python version to build the image for.
          Must be one of PY_MATRIX.keys()
      image_type: The image type to build. Must be one of
          BASE_IMAGES.keys()
      suffix: Suffix to add to the tags (e.g. "aarch64" for "ray:sha256-aarch64")
      no_cache: If True, don't use caching when building the image.
      """
  
      if image_name not in IMAGE_NAMES:
          raise ValueError(
              f"The provided image name {image_name} is not "
              f"recognized. Image names must be one of {IMAGE_NAMES}"
          )
  
      if py_version not in PY_MATRIX.keys():
          raise ValueError(
              f"The provided python version {py_version} is not "
              f"recognized. Python version must be one of"
              f" {PY_MATRIX.keys()}"
          )
  
      if image_type not in BASE_IMAGES.keys():
          raise ValueError(
              f"The provided CUDA version {image_type} is not "
              f"recognized. CUDA version must be one of"
              f" {BASE_IMAGES.keys()}"
          )
  
      build_args = {}
      build_args["PYTHON_VERSION"] = PY_MATRIX[py_version]
      # I.e. "py310"[3:] == 10
      assert py_version[:3] == "py3"
      python_minor_version = py_version[3:]
  
      constraints_file = "requirements_compiled.txt"
  
      build_args["CONSTRAINTS_FILE"] = constraints_file
  
      if platform.processor() in ADDITIONAL_PLATFORMS:
          build_args["HOSTTYPE"] = platform.processor()
  
      device_tag = f"{image_type}"
  
      if image_name == "base-deps":
          base_image = BASE_IMAGES[image_type]
      else:
          base_image = _with_suffix(
              f"-{py_version}-{device_tag}", suffix=suffix
          )
  
      if image_name != "ray-worker-container":
          build_args["BASE_IMAGE"] = base_image
  
      if image_name in ["ray", "ray-deps", "ray-worker-container"]:
          wheel = _get_wheel_name(python_minor_version)
          build_args["WHEEL_PATH"] = f".whl/{wheel}"
          # Add pip option "--find-links .whl/" to ensure ray-cpp wheel
          # can be found.
          build_args["FIND_LINKS_PATH"] = ".whl"
  
      tagged_name = f"{DOCKER_HUB_REPO}/{image_name}:nightly-{py_version}-{device_tag}"
  
      tagged_name = _with_suffix(tagged_name, suffix=suffix)
  
      for i in range(2):
          cleanup = DOCKER_CLIENT.containers.prune().get(
              "SpaceReclaimed"
          )
          if cleanup is not None:
              print(f"Cleaned up {cleanup / (2 ** 20)}MB")
  
          labels = {
              "image-name": image_name,
              "python-version": PY_MATRIX[py_version],
              "ray-commit": _COMMIT_SHA,
          }
          if image_type in CUDA_FULL:
              labels["cuda-version"] = CUDA_FULL[image_type]
  
          output = DOCKER_CLIENT.api.build(
              path=os.path.join(_get_root_dir(), "docker", image_name),
              tag=tagged_name,
              nocache=no_cache,
              labels=labels,
              buildargs=build_args,
          )
  
          cmd_output = []
          try:
              start = datetime.datetime.now()
              current_iter = start
              for line in output:
                  cmd_output.append(line.decode("utf-8"))
                  if (
                      datetime.datetime.now() - current_iter
                      >= datetime.timedelta(minutes=5)
                  ):
                      current_iter = datetime.datetime.now()
                      elapsed = datetime.datetime.now() - start
                      print(
                          f"Still building {tagged_name} after "
                          f"{elapsed.seconds} seconds"
                      )
                      if elapsed >= datetime.timedelta(minutes=15):
                          print("Additional build output:")
                          print(*cmd_output, sep="\n")
                          # Clear cmd_output after printing, so the next
                          # iteration will not print out the same lines.
                          cmd_output = []
          except Exception as e:
              print(f"FAILURE with error {e}")
  
          if len(DOCKER_CLIENT.api.images(tagged_name)) == 0:
              print(f"ERROR building: {tagged_name}. Output below:")
              print(*cmd_output, sep="\n")
              if i == 1:
                  raise Exception("FAILED TO BUILD IMAGE")
              print("TRYING AGAIN")
          else:
              break
  
      print("BUILT: ", tagged_name)
      return tagged_name
  
imports: import datetime
  import io
  import json
  import functools
  import glob
  import itertools
  import os
  import platform
  import shutil
  import subprocess
  import sys
  import tarfile
  from collections import defaultdict
  from pathlib import Path
  from typing import List, Optional, Tuple, Dict
  import click
  import docker
label_desc: Use image node_id 11 for calling a global function with example usage: _build_docker_image(image_name, py_version, image_type, suffix, no_cache) and returns: tagged_name