diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0ca8a448057a7ebe6079ec8965bd59b5469abd86..cda931f6c918bd893cd2a077deee33b0e9b286f9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -26,10 +26,50 @@
 # . See https://support.astron.nl/confluence/display/L2M/L3+SDP+Decision%3A+Gitlab+pipeline+automation+to+test+SDPFW+with+OPC+UA
 
 stages:
+    - image
     - simulation
     - synthesis
     - hardware
 
+# build docker image
+docker-image:
+  stage: image
+  image: docker:latest
+  tags:
+    - privileged
+  only:
+    refs:
+      - master
+  services:
+    - docker:dind
+  variables:
+    DOCKER_TLS_CERTDIR: "/certs"
+  before_script:
+    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+  script:
+    - |
+      if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
+        tag=""
+        echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'"
+      else
+        tag=":$CI_COMMIT_REF_SLUG"
+        echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
+      fi
+    - docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" .
+    - docker push "$CI_REGISTRY_IMAGE${tag}"
+
+lint-vhdl-libraries:
+    stage: linting
+    extends: docker-image
+    allow_failure: true
+    before_script:
+        - DEBIAN_FRONTEND=noninteractive apt-get update
+        - DEBIAN_FRONTEND=noninteractive apt-get install -y python3 python3-pip python3-ipython
+        - pip3 install vsg --use-pep517
+    script:
+        - cd libraries
+        - find . -name "*.vhd" -exec vsg -f {} \;
+
 
 ###############################################################################
 # HDL simulation stage