Example #1
0
def ExecuteDockerCommand(command):
  """Executes Docker CLI commands in subprocess.

  Just calls local_util.ExecuteCommand(cmd,...) and raises error for non-zero
  exit code.

  Args:
    command: (List[str]) Strings to send in as the command.

  Raises:
    ValueError: The input command is not a docker command.
    DockerError: An error occurred when executing the given docker command.
  """

  command_str = " ".join(command)
  if not command_str.startswith("docker"):
    raise ValueError("`{}` is not a Docker command".format("docker"))

  log.info("Running command: {}".format(command_str))

  return_code = local_util.ExecuteCommand(command)
  if return_code != 0:
    error_msg = """
        Docker failed with error code {code}.
        Command: {cmd}
        """.format(
            code=return_code, cmd=command_str)
    raise errors.DockerError(error_msg, command, return_code)
Example #2
0
def RunContainer(image, enable_gpu=False, run_args=None, user_args=None):
    """Calls `docker run` on a given image with specified arguments.

  Args:
    image: (Image) Represents the image to run, containing info like image name,
      home directory, entrypoint etc.
    enable_gpu: (bool) Whether to use GPU
    run_args: (List[str]) Extra custom options to apply to `docker run` after
      our defaults.
    user_args: (List[str]) Extra user defined arguments to supply to the
      entrypoint.

  Raises:
    DockerError: An error occurred when executing `docker run`
  """
    # TODO(b/177787660): add interactive mode option

    if run_args is None:
        run_args = []

    if user_args is None:
        user_args = []

    run_opts = _DockerRunOptions(enable_gpu, image.default_home, run_args)

    command = ["docker", "run"] + run_opts + [image.name] + user_args

    command_str = " ".join(command)
    log.info("Running command: {}".format(command_str))

    return_code = local_util.ExecuteCommand(command)
    if return_code != 0:
        error_msg = """
        Docker failed with error code {code}.
        Command: {cmd}
        """.format(code=return_code, cmd=command_str)
        raise errors.DockerError(error_msg, command, return_code)
Example #3
0
def BuildImage(base_image,
               host_workdir,
               main_script,
               output_image_name,
               python_module=None,
               requirements=None,
               extra_packages=None,
               container_workdir=None,
               container_home=None,
               no_cache=True,
               **kwargs):
  """Builds a Docker image.

  Generates a Dockerfile and passes it to `docker build` via stdin.
  All output from the `docker build` process prints to stdout.

  Args:
    base_image: (str) ID or name of the base image to initialize the build
      stage.
    host_workdir: (str) A path indicating where all the required sources
      locates.
    main_script: (str) A string that identifies the executable script under the
      working directory.
    output_image_name: (str) Name of the built image.
    python_module: (str) Represents the executable main_script in form of a
      python module, if applicable.
    requirements: (List[str]) Required dependencies to install from PyPI.
    extra_packages: (List[str]) User custom dependency packages to install.
    container_workdir: (str) Working directory in the container.
    container_home: (str) the $HOME directory in the container.
    no_cache: (bool) Do not use cache when building the image.
    **kwargs: Other arguments to pass to underlying method that generates the
      Dockerfile.

  Returns:
    A Image class that contains info of the built image.

  Raises:
    DockerError: An error occurred when executing `docker build`
  """

  tag_options = ["-t", output_image_name]

  cache_args = ["--no-cache"] if no_cache else []
  command = ["docker", "build"
            ] + cache_args + tag_options + ["--rm", "-f-", host_workdir]

  setup_path = _DEFAULT_SETUP_PATH if os.path.exists(
      _DEFAULT_SETUP_PATH) else None
  requirments_path = _DEFAULT_REQUIREMENTS_PATH if os.path.exists(
      _DEFAULT_REQUIREMENTS_PATH) else None

  home_dir = container_home or _DEFAULT_HOME
  work_dir = container_workdir or _DEFAULT_WORKDIR

  # The package will be used in Docker, thus norm it to POSIX path format.
  main_package = Package(
      script=main_script.replace(os.sep, posixpath.sep),
      package_path=host_workdir.replace(os.sep, posixpath.sep),
      python_module=python_module)

  dockerfile = _MakeDockerfile(
      base_image,
      main_package=main_package,
      container_home=home_dir,
      container_workdir=work_dir,
      requirements_path=requirments_path,
      setup_path=setup_path,
      extra_requirements=requirements,
      extra_packages=extra_packages,
      **kwargs)

  joined_command = " ".join(command)
  log.info("Running command: {}".format(joined_command))

  return_code = local_util.ExecuteCommand(command, input_str=dockerfile)
  if return_code == 0:
    return Image(output_image_name, home_dir, work_dir)
  else:
    error_msg = textwrap.dedent("""
        Docker failed with error code {code}.
        Command: {cmd}
        """.format(code=return_code, cmd=joined_command))
    raise errors.DockerError(error_msg, command, return_code)