Repository: google/turbinia

Issue:
Turbinia worker fails when DOCKER_ENABLED=True and there is no docker deamon
Add exception handling to docker code to avoid breakage Stacktrace:

```
Traceback (most recent call last):
  File "/usr/local/bin/turbiniactl", line 33, in <module>
    sys.exit(load_entry_point('turbinia==20210208.3', 'console_scripts', 'turbiniactl')())
  File "/usr/local/lib/python3.6/dist-packages/turbinia-20210208.3-py3.6.egg/turbinia/turbiniactl.py", line 662, in main
    jobs_denylist=args.jobs_denylist, jobs_allowlist=args.jobs_allowlist)
  File "/usr/local/lib/python3.6/dist-packages/turbinia-20210208.3-py3.6.egg/turbinia/client.py", line 1261, in __init__
    check_docker_dependencies(dependencies)
  File "/usr/local/lib/python3.6/dist-packages/turbinia-20210208.3-py3.6.egg/turbinia/client.py", line 145, in check_docker_dependencies
    images = docker_manager.DockerManager().list_images(return_filter='short_id')
  File "/usr/local/lib/python3.6/dist-packages/turbinia-20210208.3-py3.6.egg/turbinia/lib/docker_manager.py", line 84, in __init__
    self.client = self._create_client()
  File "/usr/local/lib/python3.6/dist-packages/turbinia-20210208.3-py3.6.egg/turbinia/lib/docker_manager.py", line 99, in _create_client
    docker_client = docker.from_env()
  File "/usr/local/lib/python3.6/dist-packages/docker/client.py", line 101, in from_env
    **kwargs_from_env(**kwargs)
  File "/usr/local/lib/python3.6/dist-packages/docker/client.py", line 45, in __init__
    self.api = APIClient(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/docker/api/client.py", line 197, in __init__
    self._version = self._retrieve_server_version()
  File "/usr/local/lib/python3.6/dist-packages/docker/api/client.py", line 222, in _retrieve_server_version
    'Error while fetching server API version: {0}'.format(e)
docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))
```


Discussion:
Add exception around https://github.com/google/turbinia/blob/508c796ff2ea2dd7e4ba7b1cfdc1e5fd7db2cc97/turbinia/client.py#L145
This happens when DOCKER_ENABLED=True and there is no docker daemon installed. In this case the code will try to connect to the docker manager, urllib will retry and docker will think it's in error and restart itself creating a loop of error/restart

Resolving patch:
diff --git a/turbinia/client.py b/turbinia/client.py
--- a/turbinia/client.py
+++ b/turbinia/client.py
@@ -1194,7 +1194,12 @@ def __init__(self, jobs_denylist=None, jobs_allowlist=None):
     # Check for valid dependencies/directories.
     dependencies = config.ParseDependencies()
     if config.DOCKER_ENABLED:
-      check_docker_dependencies(dependencies)
+      try:
+        check_docker_dependencies(dependencies)
+      except TurbiniaException as e:
+        log.warning(
+            "DOCKER_ENABLED=True is set in the config, but there is an error checking for the docker daemon: {0:s}"
+        ).format(str(e))
     check_system_dependencies(dependencies)
     check_directory(config.MOUNT_DIR_PREFIX)
     check_directory(config.OUTPUT_DIR)
@@ -1261,7 +1266,12 @@ def __init__(self, jobs_denylist=None, jobs_allowlist=None):
     # Check for valid dependencies/directories.
     dependencies = config.ParseDependencies()
     if config.DOCKER_ENABLED:
-      check_docker_dependencies(dependencies)
+      try:
+        check_docker_dependencies(dependencies)
+      except TurbiniaException as e:
+        log.warning(
+            "DOCKER_ENABLED=True is set in the config, but there is an error checking for the docker daemon: {0:s}"
+        ).format(str(e))
     check_system_dependencies(dependencies)
     check_directory(config.MOUNT_DIR_PREFIX)
     check_directory(config.OUTPUT_DIR)
diff --git a/turbinia/lib/docker_manager.py b/turbinia/lib/docker_manager.py
--- a/turbinia/lib/docker_manager.py
+++ b/turbinia/lib/docker_manager.py
@@ -101,6 +101,10 @@ def _create_client(self):
       raise TurbiniaException(
           'An issue has occurred connecting to the Docker daemon: {0!s}'.format(
               exception))
+    except docker.errors.DockerException as exception:
+      raise TurbiniaException(
+          'An issue has occurred connecting to the Docker daemon: {0!s}'.format(
+              exception))
     return docker_client
 
   def get_image(self, image_id):
diff --git a/turbinia/workers/docker.py b/turbinia/workers/docker.py
--- a/turbinia/workers/docker.py
+++ b/turbinia/workers/docker.py
@@ -17,6 +17,7 @@
 
 import json
 import logging
+from os import path
 import subprocess
 
 from turbinia import TurbiniaException
@@ -64,6 +65,11 @@ def GetContainers(self, evidence):
     if not de_binary:
       raise TurbiniaException('Cannot find de.py in path')
 
+    # Check if docker folder exists
+    if not path.exists(docker_dir):
+      log.info('docker_dir does not exist')
+      return containers_info
+
     docker_explorer_command = ['sudo', de_binary]
 
     if config.DEBUG_TASKS or evidence.config.get('debug_tasks'):


Test patch: