class_docstr: This EnvironmentDriver handles environment management in the project using docker
  
  Parameters
  ----------
  root : str, optional
      home filepath for project
      (default is empty)
  docker_execpath : str, optional
      execution path for docker
      (default is "docker" which defers to system)
  docker_socket : str, optional
      socket path to docker daemon to connect
      (default is None, this takes the default path for the system)
  
  Attributes
  ----------
  root : str
      home filepath for project
  datmo_directory_name : str
      datmo directory name for project
  docker_execpath : str, optional
      docker execution path for the system
  docker_socket : str, optional
      specific socket for docker
      (default is None, which means system default is used by docker)
  client : DockerClient
      docker python api client
  cpu_prefix : list
      list of strings for the prefix command for all docker commands
  info : dict
      information about the docker daemon connection
  is_connected : bool
      True if connected to daemon else False
  type : str
      type of EnvironmentDriver
class_docstr_tok: ["This","EnvironmentDriver","handles","environment","management","in","the","project","using","docker","Parameters","--","--","--","--","--","root",":","str",",","optional","home","filepath","for","project","(","default","is","empty",")","docker_execpath",":","str",",","optional","execution","path","for","docker","(","default","is","``","docker","''","which","defers","to","system",")","docker_socket",":","str",",","optional","socket","path","to","docker","daemon","to","connect","(","default","is","None",",","this","takes","the","default","path","for","the","system",")","Attributes","--","--","--","--","--","root",":","str","home","filepath","for","project","datmo_directory_name",":","str","datmo","directory","name","for","project","docker_execpath",":","str",",","optional","docker","execution","path","for","the","system","docker_socket",":","str",",","optional","specific","socket","for","docker","(","default","is","None",",","which","means","system","default","is","used","by","docker",")","client",":","DockerClient","docker","python","api","client","cpu_prefix",":","list","list","of","strings","for","the","prefix","command","for","all","docker","commands","info",":","dict","information","about","the","docker","daemon","connection","is_connected",":","bool","True","if","connected","to","daemon","else","False","type",":","str","type","of","EnvironmentDriver"]
docstr: Run Docker container with parameters given as defined below
  Parameters
  ----------
  image_name : str
      Docker image name
  command : list, optional
      List with complete user-given command (e.g. ["python3", "cool.py"])
  ports : list, optional
      Here are some example ports used for common applications.
         *  "jupyter notebook" - 8888
         *  flask API - 5000
         *  tensorboard - 6006
      An example input for the above would be ["8888:8888", "5000:5000", "6006:6006"]
      which maps the running host port (right) to that of the environment (left)
  name : str, optional
      User given name for container
  volumes : dict, optional
      Includes storage volumes for docker
      (e.g. { outsidepath1 : {"bind", containerpath2, "mode", MODE} })
  mem_limit : str, optional
      maximum amount of memory the container can use
      (these options take a positive integer, followed by a suffix of b, k, m, g, to indicate bytes, kilobytes,
      megabytes, or gigabytes. memory limit is contrained by total memory of the VM in which docker runs)
  detach : bool, optional
      True if container is to be detached else False
  stdin_open : bool, optional
      True if stdin is open else False
  tty : bool, optional
      True to connect pseudo-terminal with stdin / stdout else False
  api : bool, optional
      True if Docker python client should be used else use subprocess
  Returns
  -------
  if api=False:
  return_code: int
      integer success code of command
  container_id: str
      output container id
  if api=True & if detach=True:
  container_obj: Container
      object from Docker python api with details about container
  if api=True & if detach=False:
  logs: str
      output logs for the run function
  Raises
  ------
  EnvironmentExecutionError
       error in running the environment command
docstr_tok: ["Run","Docker","container","with","parameters","given","as","defined","below","Parameters","--","--","--","--","--","image_name",":","str","Docker","image","name","command",":","list",",","optional","List","with","complete","user-given","command","(","e.g",".","[","``","python3","''",",","``","cool.py","''","]",")","ports",":","list",",","optional","Here","are","some","example","ports","used","for","common","applications",".","*","``","jupyter","notebook","''","-","8888","*","flask","API","-","5000","*","tensorboard","-","6006","An","example","input","for","the","above","would","be","[","``","8888:8888","''",",","``","5000:5000","''",",","``","6006:6006","''","]","which","maps","the","running","host","port","(","right",")","to","that","of","the","environment","(","left",")","name",":","str",",","optional","User","given","name","for","container","volumes",":","dict",",","optional","Includes","storage","volumes","for","docker","(","e.g",".","{","outsidepath1",":","{","``","bind","''",",","containerpath2",",","``","mode","''",",","MODE","}","}",")","mem_limit",":","str",",","optional","maximum","amount","of","memory","the","container","can","use","(","these","options","take","a","positive","integer",",","followed","by","a","suffix","of","b",",","k",",","m",",","g",",","to","indicate","bytes",",","kilobytes",",","megabytes",",","or","gigabytes",".","memory","limit","is","contrained","by","total","memory","of","the","VM","in","which","docker","runs",")","detach",":","bool",",","optional","True","if","container","is","to","be","detached","else","False","stdin_open",":","bool",",","optional","True","if","stdin","is","open","else","False","tty",":","bool",",","optional","True","to","connect","pseudo-terminal","with","stdin","\/","stdout","else","False","api",":","bool",",","optional","True","if","Docker","python","client","should","be","used","else","use","subprocess","Returns","--","--","--","-","if","api=False",":","return_code",":","int","integer","success","code","of","command","container_id",":","str","output","container","id","if","api=True","&","if","detach=True",":","container_obj",":","Container","object","from","Docker","python","api","with","details","about","container","if","api=True","&","if","detach=False",":","logs",":","str","output","logs","for","the","run","function","Raises","--","--","--","EnvironmentExecutionError","error","in","running","the","environment","command"]
code: def run_container(
      self,
      image_name,
      command=None,
      ports=None,
      name=None,
      volumes=None,
      mem_limit=None,
      runtime=None,
      detach=False,
      stdin_open=False,
      tty=False,
      api=False,
  ):
      """Run Docker container with parameters given as defined below
      Parameters
      ----------
      image_name : str
          Docker image name
      command : list, optional
          List with complete user-given command (e.g. ["python3", "cool.py"])
      ports : list, optional
          Here are some example ports used for common applications.
             *  "jupyter notebook" - 8888
             *  flask API - 5000
             *  tensorboard - 6006
          An example input for the above would be ["8888:8888", "5000:5000", "6006:6006"]
          which maps the running host port (right) to that of the environment (left)
      name : str, optional
          User given name for container
      volumes : dict, optional
          Includes storage volumes for docker
          (e.g. { outsidepath1 : {"bind", containerpath2, "mode", MODE} })
      mem_limit : str, optional
          maximum amount of memory the container can use
          (these options take a positive integer, followed by a suffix of b, k, m, g, to indicate bytes, kilobytes,
          megabytes, or gigabytes. memory limit is contrained by total memory of the VM in which docker runs)
      detach : bool, optional
          True if container is to be detached else False
      stdin_open : bool, optional
          True if stdin is open else False
      tty : bool, optional
          True to connect pseudo-terminal with stdin / stdout else False
      api : bool, optional
          True if Docker python client should be used else use subprocess
      Returns
      -------
      if api=False:
      return_code: int
          integer success code of command
      container_id: str
          output container id
      if api=True & if detach=True:
      container_obj: Container
          object from Docker python api with details about container
      if api=True & if detach=False:
      logs: str
          output logs for the run function
      Raises
      ------
      EnvironmentExecutionError
           error in running the environment command
      """
      try:
          if api:  # calling the docker client via the API
              # TODO: Test this out for the API (need to verify ports work)
              if detach:
                  command = " ".join(command) if command else command
                  container = self.client.containers.run(
                      image_name,
                      command,
                      ports=ports,
                      name=name,
                      volumes=volumes,
                      mem_limit=mem_limit,
                      detach=detach,
                      stdin_open=stdin_open,
                  )
                  return container
              else:
                  command = " ".join(command) if command else command
                  logs = self.client.containers.run(
                      image_name,
                      command,
                      ports=ports,
                      name=name,
                      volumes=volumes,
                      mem_limit=mem_limit,
                      detach=detach,
                      stdin_open=stdin_open,
                  )
                  return logs.decode()
          else:  # if calling run function with the shell commands
              docker_shell_cmd_list = list(self.prefix)
              docker_shell_cmd_list.append("run")
  
              if name:
                  docker_shell_cmd_list.append("--name")
                  docker_shell_cmd_list.append(name)
  
              if runtime:
                  docker_shell_cmd_list.append("--runtime")
                  docker_shell_cmd_list.append(runtime)
  
              if mem_limit:
                  docker_shell_cmd_list.append("-m")
                  docker_shell_cmd_list.append(mem_limit)
                  docker_shell_cmd_list.append("--memory-swap")
                  docker_shell_cmd_list.append("-1")
  
              if stdin_open:
                  docker_shell_cmd_list.append("-i")
  
              if tty:
                  docker_shell_cmd_list.append("-t")
  
              if detach:
                  docker_shell_cmd_list.append("-d")
  
              # Volume
              if volumes:
                  # Mounting volumes
                  for key in list(volumes):
                      docker_shell_cmd_list.append("-v")
                      volume_mount = (
                          key
                          + ":"
                          + volumes[key]["bind"]
                          + ":"
                          + volumes[key]["mode"]
                      )
                      docker_shell_cmd_list.append(volume_mount)
  
              if ports:
                  # Mapping ports
                  for mapping in ports:
                      docker_shell_cmd_list.append("-p")
                      docker_shell_cmd_list.append(mapping)
  
              docker_shell_cmd_list.append(image_name)
              if command:
                  docker_shell_cmd_list.extend(command)
              return_code = subprocess.call(docker_shell_cmd_list)
              if return_code != 0:
                  raise EnvironmentExecutionError(
                      __(
                          "error",
                          "controller.environment.driver.docker.run_container",
                          str(docker_shell_cmd_list),
                      )
                  )
              list_process_cmd = list(self.prefix)
              list_process_cmd.extend(["ps", "-q", "-l"])
              process = subprocess.Popen(
                  list_process_cmd,
                  stdout=subprocess.PIPE,
                  stderr=subprocess.PIPE,
              )
              stdout, stderr = process.communicate()
              if process.returncode > 0:
                  raise EnvironmentExecutionError(
                      __(
                          "error",
                          "controller.environment.driver.docker.run_container",
                          str(stderr),
                      )
                  )
              container_id = stdout.decode().strip()
      except subprocess.CalledProcessError as e:
          raise EnvironmentExecutionError(
              __(
                  "error",
                  "controller.environment.driver.docker.run_container",
                  str(e),
              )
          )
      return return_code, container_id
  
imports: import ast
  import os
  import shutil
  import re
  import time
  import json
  import subprocess
  import platform
  from io import open
  from docker import DockerClient
  from docker import errors
  from datmo.core.util.i18n import get
  from datmo.core.util.exceptions import PathDoesNotExist, EnvironmentInitFailed, EnvironmentConnectFailed, EnvironmentExecutionError, FileAlreadyExistsError, EnvironmentRequirementsCreateError, EnvironmentImageNotFound, EnvironmentContainerNotFound, GPUSupportNotEnabled, EnvironmentDoesNotExist, FileStructureError
  from datmo.core.controller.environment.driver import EnvironmentDriver
label_desc: Use image node_id 29 for calling the DockerEnvironmentDriver obj's underlying member method code with example usage: obj.run_container(image_name, command, ports, name, volumes, mem_limit, runtime, detach, stdin_open, tty, api) and returns: return_code,  container_id, container, logs