### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

After a clean install using `pip install localstack`, running `localstack start` fails by producing the following output:

```

     __                     _______ __             __
    / /   ____  _________ _/ / ___// /_____ ______/ /__
   / /   / __ \/ ___/ __ `/ /\__ \/ __/ __ `/ ___/ //_/
  / /___/ /_/ / /__/ /_/ / /___/ / /_/ /_/ / /__/ ,<
 /_____/\____/\___/\__,_/_//____/\__/\__,_/\___/_/|_|

 💻 LocalStack CLI 0.14.2.11

Traceback (most recent call last):
  File "/home/phii/Code/aws-test/.venv/bin/localstack", line 23, in <module>
    main()
  File "/home/phii/Code/aws-test/.venv/bin/localstack", line 19, in main
    main.main()
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/localstack/cli/main.py", line 6, in main
    cli()
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/localstack/cli/plugin.py", line 15, in __call__
    self.group(*args, **kwargs)
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/localstack/cli/localstack.py", line 125, in cmd_start
    from localstack.utils import bootstrap
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/localstack/utils/bootstrap.py", line 16, in <module>
    from localstack.utils.container_networking import get_main_container_name
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/localstack/utils/container_networking.py", line 7, in <module>
    from localstack.utils.container_utils.container_client import ContainerException
  File "/home/phii/Code/aws-test/.venv/lib/python3.7/site-packages/localstack/utils/container_utils/container_client.py", line 13, in <module>
    from typing import Dict, List, Optional, Protocol, Tuple, Union
ImportError: cannot import name 'Protocol' from 'typing' (/home/phii/.pyenv/versions/3.7.4/lib/python3.7/typing.py)
```

As you can see from the logs, I am using python 3.7.4.
After googling the python docs, I saw that "Protocol" wasn't added to the "typing" module until subsequent python versions, however the docs clearly state that localstack supports python 3.7.

### Expected Behavior

I expected for localstack to start normally.

### How are you starting LocalStack?

Custom (please describe below)

### Steps To Reproduce

#### How are you starting localstack (e.g., `bin/localstack` command, arguments, or `docker-compose.yml`)

`bin/localstack`

#### Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)

`localstack start`

### Environment

```markdown
- OS: ManjaroLinux 21.2.6
- LocalStack: latest
```
if isinstance(current_value, dict) and path_node in current_value:
            current_value = current_value[path_node]
        elif isinstance(current_value, list) and path_node < len(current_value):
            current_value = current_value[path_node]
        else:
            current_value = None
    return current_value or default_value
def set_safe_mutable(dictionary, path, value):
    """
    Mutates original dict and sets the specified value under provided path.
    :type dictionary: dict
    :param dictionary: Dict to mutate.
    :type path: list|str
    :param path: List or dot-separated string containing the path of an attribute,
                 starting from the root node "$".
    :type value: any
    :param value: Value to set under specified path.
    :rtype: dict
    :return: Returns mutated dictionary.
    """
    if not isinstance(dictionary, dict):
        raise AttributeError('"dictionary" must be of type "dict"')
    attribute_path = path if isinstance(path, list) else path.split(".")
    attribute_path_len = len(attribute_path)
    if attribute_path_len == 0 or attribute_path[0] != "$":
        raise AttributeError('Dict navigation must begin with a root node "$"')
    current_pointer = dictionary
    for i in range(attribute_path_len):
        path_node = attribute_path[i]
        if path_node == "$":