diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 299c9ee5ed7533924f144411439f99e665f4645b..365219d5716e2beb06f1e862c46d20926723530a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,45 +1,55 @@
-stages:
-  - build
-  - deploy
-
-variables:
-  DOCKER_IMAGE: $DOCKER_USERNAME/neo4j-populator
-  KUBE_NAMESPACE: $KUBE_NAMESPACE
-
-.default-docker:
-  image: docker:24.0
-  services:
-    - docker:24.0-dind
-  before_script:
-    - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
-
-build_and_push:
-  stage: build
-  extends: .default-docker
-  script:
-    - docker build -t $DOCKER_IMAGE:latest .
-    - docker push $DOCKER_IMAGE:latest
-
-setup_kubeconfig:
-  stage: deploy
-  image: bitnami/kubectl:latest
-  script:
-    - mkdir -p ~/.kube
-    - echo "$KUBECONFIG_CONTENT" > ~/.kube/config
-    - chmod 600 ~/.kube/config
-  artifacts:
-    paths:
-      - ~/.kube/config
-
-deploy_to_kubernetes:
-  stage: deploy
-  image: bitnami/kubectl:latest
-  dependencies:
-    - setup_kubeconfig
-  script:
-    - kubectl -n "$KUBE_NAMESPACE" delete -f ./deployment-neo4j.yml --ignore-not-found
-    - kubectl -n "$KUBE_NAMESPACE" delete -f ./neo4j-service.yml --ignore-not-found
-    - kubectl -n "$KUBE_NAMESPACE" delete -f ./job-db-populator.yml --ignore-not-found
-    - kubectl -n "$KUBE_NAMESPACE" apply -f ./deployment-neo4j.yml
-    - kubectl -n "$KUBE_NAMESPACE" apply -f ./neo4j-service.yml
-    - kubectl -n "$KUBE_NAMESPACE" apply -f ./job-db-populator.yml
+name: CI/CD - Build & Deploy
+
+on:
+  push:
+    branches:
+      - main
+  workflow_dispatch:
+
+jobs:
+  build-and-deploy:
+    runs-on: ubuntu-latest
+
+    env:
+      DOCKER_IMAGE: ${{ secrets.DOCKER_USERNAME }}/neo4j-populator
+      KUBE_NAMESPACE: ${{ secrets.KUBE_NAMESPACE }}
+
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+
+      - name: Login to Docker Hub
+        uses: docker/login-action@v3
+        with:
+          username: ${{ secrets.DOCKER_USERNAME }}
+          password: ${{ secrets.DOCKER_PASSWORD }}
+
+      - name: Build and push Docker image
+        uses: docker/build-push-action@v5
+        with:
+          context: .
+          file: ./Dockerfile
+          push: true
+          tags: |
+            ${{ env.DOCKER_IMAGE }}:latest
+            ${{ env.DOCKER_IMAGE }}:${{ github.sha }}
+
+      - name: Set up Kubeconfig
+        run: |
+          mkdir -p .kube
+          echo "${{ secrets.KUBECONFIG }}" > .kube/config.yml
+
+      - name: Delete old Kubernetes resources
+        run: |
+          kubectl --kubeconfig=.kube/config.yml -n $KUBE_NAMESPACE delete -f ./deployment-neo4j.yml --ignore-not-found
+          kubectl --kubeconfig=.kube/config.yml -n $KUBE_NAMESPACE delete -f ./neo4j-service.yml --ignore-not-found
+          kubectl --kubeconfig=.kube/config.yml -n $KUBE_NAMESPACE delete -f ./job-db-populator.yml --ignore-not-found
+
+      - name: Apply new Kubernetes configuration
+        run: |
+          kubectl --kubeconfig=.kube/config.yml -n $KUBE_NAMESPACE apply -f ./deployment-neo4j.yml
+          kubectl --kubeconfig=.kube/config.yml -n $KUBE_NAMESPACE apply -f ./neo4j-service.yml
+          kubectl --kubeconfig=.kube/config.yml -n $KUBE_NAMESPACE apply -f ./job-db-populator.yml