diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..54b972527c78b5fbd5947b0a98bb427bb657a32f
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,127 @@
+stages:
+  - build
+  - deploy_to_test
+  - deploy_to_production
+
+workflow:
+  rules:
+    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+      variables:
+        DOCKER_BUILD_IMAGE_TAG: ":stable"
+        DOCKER_IMAGE_TAG: ":latest"
+    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH
+      variables:
+        DOCKER_BUILD_IMAGE_TAG: ":latest"
+        DOCKER_IMAGE_TAG: ":$CI_COMMIT_REF_NAME"
+
+
+docker-test-build:
+  variables:
+    if: main
+  # Official docker image.
+  image: docker$DOCKER_BUILD_IMAGE_TAG
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  stage: build
+  services:
+    - docker:dind
+  script:
+    - docker build --pull -t "$CI_REGISTRY_IMAGE$DOCKER_IMAGE_TAG" adex-backend-fastapi
+    - docker push $CI_REGISTRY_IMAGE$DOCKER_IMAGE_TAG
+
+
+docker-build-master:
+  # Official docker image.
+  image: docker$DOCKER_BUILD_IMAGE_TAG
+  stage: build
+  services:
+    - docker:dind
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    - docker build --pull -t "$CI_REGISTRY_IMAGE" adex-backend-fastapi
+    - docker push "$CI_REGISTRY_IMAGE"
+  only:
+    - main
+
+
+# deploy test/dev version on 'sdc-dev.astron.nl'
+docker-deploy-main-test:
+  stage: deploy_to_test
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+    ##
+    ## Install ssh-agent if not already installed, it is required by Docker.
+    ## (change apt-get to yum if you use an RPM-based image)
+    ##
+    - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client rsync -y )'
+    ##
+    ## Run ssh-agent (inside the build environment)
+    ##
+    - eval $(ssh-agent -s)
+    ##
+    ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
+    ## We're using tr to fix line endings which makes ed25519 keys work
+    ## without extra base64 encoding.
+    ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
+    ##
+    ##
+    ## Create the SSH directory and give it the right permissions
+    ##
+    - echo "$SSH_PRIVATE_KEY_USER_SDC" | tr -d '\r' | ssh-add -
+    - mkdir -p ~/.ssh
+    - chmod 700 ~/.ssh
+    - ssh-keyscan dop814.astron.nl >> ~/.ssh/known_hosts
+    - ssh-keyscan sdc-dev.astron.nl >> ~/.ssh/known_hosts
+    - chmod 644 ~/.ssh/known_hosts
+  script:
+    ## deploy the docker-compose file and use it to spin up the containers
+    - scp -o StrictHostKeyChecking=no adex-backend-fastapi/docker/docker-compose-dev-cd.yml sdc@dop814.astron.nl:/docker_compose/adex-backend-fastapi/docker-compose-dev-cd.yml
+    - ssh -o StrictHostKeyChecking=no sdc@dop814.astron.nl "echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY"
+    - ssh -o StrictHostKeyChecking=no sdc@dop814.astron.nl "docker pull "$CI_REGISTRY_IMAGE""
+    - ssh -o StrictHostKeyChecking=no sdc@dop814.astron.nl "docker-compose -p adex-backend-fastapi -f /docker_compose/adex-backend-fastapi/docker-compose-dev-cd.yml up -d"
+    - echo "Application deployed"
+  when: manual
+  only:
+    - main
+
+docker-deploy-main-production:
+  #  image: docker:latest
+  stage: deploy_to_production
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+    ##
+    ## Install ssh-agent if not already installed, it is required by Docker.
+    ## (change apt-get to yum if you use an RPM-based image)
+    ##
+    - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client rsync -y )'
+    ##
+    ## Run ssh-agent (inside the build environment)
+    ##
+    - eval $(ssh-agent -s)
+    ##
+    ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
+    ## We're using tr to fix line endings which makes ed25519 keys work
+    ## without extra base64 encoding.
+    ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
+    ##
+    ##
+    ## Create the SSH directory and give it the right permissions
+    ##
+    - echo "$SSH_PRIVATE_KEY_USER_SDC" | tr -d '\r' | ssh-add -
+    - mkdir -p ~/.ssh
+    - chmod 700 ~/.ssh
+    - ssh-keyscan dop821.astron.nl >> ~/.ssh/known_hosts
+    - ssh-keyscan sdc.astron.nl >> ~/.ssh/known_hosts
+    - chmod 644 ~/.ssh/known_hosts
+  script:
+    ## deploy the docker-compose file and use it to spin up the containers
+    - scp -o StrictHostKeyChecking=no adex-backend-fastapi/docker/docker-compose-production-cd.yml sdco@dop821.astron.nl:/opt/dockercompose/adex-backend-fastapi/docker-compose-production-cd.yml
+    - ssh -o StrictHostKeyChecking=no sdco@dop821.astron.nl "echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY"
+    - ssh -o StrictHostKeyChecking=no sdco@dop821.astron.nl "docker pull "$CI_REGISTRY_IMAGE""
+    - ssh -o StrictHostKeyChecking=no sdco@dop821.astron.nl "docker-compose -p adex-backend-fastapi -f /opt/dockercompose/adex-backend-fastapi/docker-compose-production-cd.yml up -d"
+    - echo "Application deployed"
+  when: manual
+  only:
+    - main
+
diff --git a/docker/docker-compose-dev-cd.yml b/docker/docker-compose-dev-cd.yml
new file mode 100644
index 0000000000000000000000000000000000000000..667ce7aef86153ae3647ee4032011c5376c14951
--- /dev/null
+++ b/docker/docker-compose-dev-cd.yml
@@ -0,0 +1,51 @@
+version: '3.4'
+networks:
+  adex_network:
+  traefik_proxy:
+    external:
+      name: traefik_proxy
+  default:
+    driver: bridge
+
+services:
+  adex-cache-db:
+    image: postgres:14
+    container_name: adex-cache-db
+    expose:
+      - "5432"
+    ports:
+      # enables an external database connection to sdc-dev.astron.nl:132000
+      - "13000:5432"
+    networks:
+      - traefik_proxy
+      - adex_network
+    env_file:
+      - $HOME/shared/adex_backend.env
+    volumes:
+      - adex-cache-db:/var/lib/postgresql/data
+    restart: always
+
+  adex-backend-fastapi:
+    container_name: adex-backend-fastapi
+    image: git.astron.nl:5000/astron-sdc/adex-backend-fastapi:latest
+
+    expose:
+      - "8000"
+    networks:
+      - traefik_proxy
+      - adex_network
+    labels:
+      - "traefik.enable=true"
+      - "traefik.http.routers.ldv-specification.entryPoints=websecure"
+      - "traefik.http.routers.ldv-specification.service=adex-backend-fastapi"
+      - "traefik.http.routers.ldv-specification.rule=Host(`sdc-dev.astron.nl`) && PathPrefix(`/adex-backend-fastapi`)"
+      - "traefik.http.services.ldv-specification.loadbalancer.server.port=8000"
+
+    depends_on:
+      - adex-cache-db
+    env_file:
+    - $HOME/shared/adex_backend.env
+    restart: always
+
+volumes:
+  adex-cache-db:
\ No newline at end of file
diff --git a/docker/docker-compose-production-cd.yml b/docker/docker-compose-production-cd.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5bd86d121f37f2661d67a66a9972ce88bed4f834
--- /dev/null
+++ b/docker/docker-compose-production-cd.yml
@@ -0,0 +1,51 @@
+version: '3.4'
+networks:
+  adex_network:
+  traefik_proxy:
+    external:
+      name: traefik_proxy
+  default:
+    driver: bridge
+
+services:
+  adex-cache-db:
+    image: postgres:14
+    container_name: adex-cache-db
+    expose:
+      - "5432"
+    ports:
+      # enables an external database connection to sdc.astron.nl:13000
+      - "13000:5432"
+    networks:
+      - traefik_proxy
+      - adex_network
+    env_file:
+      - $HOME/shared/adex_backend.env
+    volumes:
+      - adex-cache-db:/var/lib/postgresql/data
+    restart: always
+
+  adex-backend-fastapi:
+    container_name: adex-backend-fastapi
+    image: git.astron.nl:5000/astron-sdc/adex-backend-fastapi:latest
+
+    expose:
+      - "8000"
+    networks:
+      - traefik_proxy
+      - adex_network
+    labels:
+      - "traefik.enable=true"
+      - "traefik.http.routers.ldv-specification.entryPoints=websecure"
+      - "traefik.http.routers.ldv-specification.service=adex-backend-fastapi"
+      - "traefik.http.routers.ldv-specification.rule=Host(`sdc.astron.nl`) && PathPrefix(`/adex-backend-fastapi`)"
+      - "traefik.http.services.ldv-specification.loadbalancer.server.port=8000"
+
+    depends_on:
+      - adex-cache-db
+    env_file:
+    - $HOME/shared/adex_backend.env
+    restart: always
+
+volumes:
+  adex-cache-db:
\ No newline at end of file