diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 11a677ede598459d0aa6434f92c9cf02b4e5917d..7ec4979760f7622575b68b059c2bca0b36b5572e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -33,7 +33,7 @@ default:
 stages: # List of stages for jobs, and their order of execution
 #  - build
   - test
-#  - deploy
+  - deploy
 
 integration-test-job: # Runs integration tests with the database
   stage: test
@@ -114,8 +114,36 @@ lint-test-job: # Runs linters checks on code
   script:
     - ./scripts/lint.sh
 
-#deploy-job:      # This job runs in the deploy stage.
-#  stage: deploy  # It only runs when *both* jobs in the test stage complete successfully.
-#  script:
-#    - echo "Deploying application..."
-#    - echo "Application successfully deployed."
+build-publish-dev-docker-container-job:
+  stage: deploy
+  image:
+    name: gcr.io/kaniko-project/executor:v1.9.1-debug
+    entrypoint: [""]
+  only:
+    refs:
+      - development
+  before_script:
+    - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"},\"$CI_DEPENDENCY_PROXY_SERVER\":{\"auth\":\"$(printf "%s:%s" ${CI_DEPENDENCY_PROXY_USER} "${CI_DEPENDENCY_PROXY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
+  script:
+    - /kaniko/executor
+      --context "${CI_PROJECT_DIR}"
+      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
+      --destination "${CI_REGISTRY_IMAGE}:dev-${CI_COMMIT_SHA}"
+
+build-publish-docker-container-job:
+  stage: deploy
+  image:
+    name: gcr.io/kaniko-project/executor:v1.9.1-debug
+    entrypoint: [""]
+  only:
+    - tags
+  before_script:
+    - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"},\"$CI_DEPENDENCY_PROXY_SERVER\":{\"auth\":\"$(printf "%s:%s" ${CI_DEPENDENCY_PROXY_USER} "${CI_DEPENDENCY_PROXY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
+  script:
+    - /kaniko/executor
+      --context "${CI_PROJECT_DIR}"
+      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
+      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
+      --destination "${CI_REGISTRY_IMAGE}:$(echo ${CI_COMMIT_TAG} | cut -d'.' -f1-2)"
+      --destination "${CI_REGISTRY_IMAGE}:$(echo ${CI_COMMIT_TAG} | cut -d'.' -f1)"
+      --destination "${CI_REGISTRY_IMAGE}:latest"
diff --git a/Dockerfile b/Dockerfile
index e4434f1cfbdbb6027d619b745932f519d8220583..c80d4d76b8766555e52d1a5c04ed8b3e1ae9147d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,18 +1,22 @@
 FROM python:3.10-slim
-WORKDIR /code
-ENV PYTHONPATH=/code
-EXPOSE 80
+EXPOSE 8000
 
 # dumb-init forwards the kill signal to the python process
 RUN apt-get update && apt-get -y install dumb-init curl
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
-HEALTHCHECK --interval=35s --timeout=4s CMD curl -f http://localhost/health || exit 1
+HEALTHCHECK --interval=35s --timeout=4s CMD curl -f http://localhost:8000/health || exit 1
 
-COPY requirements.txt ./requirements.txt
+RUN useradd -m worker
+USER worker
+WORKDIR /home/worker/code
+ENV PYTHONPATH=/home/worker/code
+ENV PATH="/home/worker/.local/bin:${PATH}"
 
-RUN pip install --no-cache-dir --upgrade -r requirements.txt
+COPY --chown=worker:worker requirements.txt ./requirements.txt
 
-COPY . .
+RUN pip install --user --no-cache-dir --upgrade -r requirements.txt
+
+COPY --chown=worker:worker . .
 
 CMD ["./start_service.sh"]
diff --git a/start_service.sh b/start_service.sh
index b53d9f550fcba82c8d9d6395eefcdd97721a6a5c..9f1b8531af93a1f56a4e1dc16a69c77963dd9940 100755
--- a/start_service.sh
+++ b/start_service.sh
@@ -6,4 +6,4 @@ python app/check_ceph_connection.py
 python app/check_database_connection.py
 
 # Start webserver
-uvicorn app.main:app --host 0.0.0.0 --port 80
+uvicorn app.main:app --host 0.0.0.0 --port 8000