diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d79885bc72c3516de368c054cae7fbe162c74010..1a6c751b60256453385612cc831493f02d785e12 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,6 +13,9 @@ linting:
 
 tests:
   stage: test
+  variables:
+    NORTH_DOCKER_URL: ${CI_TARGET_DOCKER_ENV_URL}
+    NORTH_DOCKER_NAME_PREFIX: north-${CI_COMMIT_REF_NAME}
   script:
     - pip install -e .
     - python -m pytest --cov=north -sv tests
diff --git a/README.md b/README.md
index 407fe385f993ecb8a60952fac91710a9d4d5c33a..f4410bbbb2487f1369f26eb5cfbf6868ce66fc7b 100644
--- a/README.md
+++ b/README.md
@@ -66,3 +66,15 @@ We recomment using vs-code. Here are vs-code settings that match the CI/CD linti
 - `tests` - The [pytest](https://docs.pytest.org/) tests
 - `setup.py` - Install the package with pip
 - `docker` - All the docker files, scripts for creating/managing images, documentation
+
+
+## Architecture
+
+North is supposed to be run stand alone or as part of a NOMAD Oasis. Currently, we are
+only targeting docker as the environment to run tools.
+
+![with NOMAD Oasis on dev cluster](docs/assets/north-oasis-architecture.png)
+
+- all containers that are run need to have an explicit name and this name has to be prefixed
+with `north.config.docker_name_prefix`. This will allow us to target docker environments
+that are used by other services.
diff --git a/docs/assets/north-oasis-architecture.png b/docs/assets/north-oasis-architecture.png
new file mode 100644
index 0000000000000000000000000000000000000000..0af7b00476ac70cc62dd86c8731d116cedd39ca4
Binary files /dev/null and b/docs/assets/north-oasis-architecture.png differ
diff --git a/north/config.py b/north/config.py
index c4d22eba8f3445d9b11f1bba1da64703cbb61b42..b9ab171582fd3a9a3b21bf25ab197dfd05a2d377 100644
--- a/north/config.py
+++ b/north/config.py
@@ -21,7 +21,7 @@ This config file is based on pydantic's
 [settings management](https://pydantic-docs.helpmanual.io/usage/settings/).
 '''
 
-from typing import Dict, Any
+from typing import Dict, Any, Optional
 from pydantic import Field, BaseSettings
 import yaml
 import os.path
@@ -29,6 +29,19 @@ import os
 
 
 class NorthConfig(BaseSettings):
+    docker_url: Optional[str] = Field(
+        None,
+        description=(
+            'The URL to remotely (or locally) connect to the docker engine API. '
+            'If this is not given, the docker config will be read from the local env.'))
+
+    docker_name_prefix: str = Field(
+        'north',
+        description=(
+            'A prefix used for all container names. This can be used to avoid collisions '
+            'with other services using the same docker environment.')
+    )
+
     secret: str = Field(
         'this is a secret',
         description='The secret for generating JWT tokens and other cryptographic material.')
diff --git a/requirements.txt b/requirements.txt
index d163dab93a43d0f0216a2fab132ea5bc812d9e67..4fca4c4feab7c21db14d7545bbf70176bc15d103 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,3 +10,4 @@ pytest-cov
 types-PyYAML
 types-requests
 uvicorn
+docker
diff --git a/tests/test_docker.py b/tests/test_docker.py
new file mode 100644
index 0000000000000000000000000000000000000000..b15c9dae0bfd25856c103746862cdec644453b40
--- /dev/null
+++ b/tests/test_docker.py
@@ -0,0 +1,59 @@
+#
+# Copyright The NOMAD Authors.
+#
+# This file is part of NOMAD. See https://nomad-lab.eu for further info.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import pytest
+import docker
+from docker import DockerClient
+
+from north import config
+
+
+@pytest.fixture(scope='session')
+def docker_client() -> DockerClient:
+    '''
+    A session fixture for using docker. It will try to remove all left-over containers
+    after the test session.
+    '''
+    if config.docker_url:
+        docker_client = DockerClient(base_url=config.docker_url)
+    else:
+        docker_client = docker.from_env()
+
+    yield docker_client
+
+    # Remove old containrs that might be leftover from failing tests
+    docker_name_prefix_filter = dict(filters=dict(name=f'{config.docker_name_prefix}-.*'))
+    for container in docker_client.containers.list(**docker_name_prefix_filter):
+        container.stop()
+    for container in docker_client.containers.list(**docker_name_prefix_filter, all=True):
+        container.remove()
+
+
+def assert_container(docker_client: DockerClient, name: str, remove: bool = False):
+    container = docker_client.containers.get(name)
+    assert container is not None
+    if remove:
+        container.remove()
+
+
+def test_run_hello(docker_client: DockerClient):
+    name = f'{config.docker_name_prefix}-test-hello-world'
+    results = docker_client.containers.run('ubuntu:latest', 'echo hello world', name=name)
+
+    assert results == b'hello world\n', results
+    assert_container(docker_client, name, remove=True)