diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0b8a9197f61023d24b359083fc419e1bd06b51d2..596bb59c45d17ae63d3faf40d6de065707adf92e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,7 +4,7 @@ variables:
 stages:
   - build
 
-build-tags:
+build-tag:
   image: docker:latest
   stage: build
   services:
@@ -33,20 +33,14 @@ build-tags:
     - cd ./testing && ./gitlab_test.sh
     - if [ $? -ne 0 ]; then exit 1; fi  # actually fail build
     - docker push "$IMAGE_1":$CI_COMMIT_TAG
-    - docker push "$IMAGE_1":latest
     - docker push "$IMAGE_2":$CI_COMMIT_TAG
-    - docker push "$IMAGE_2":latest
     - docker push "$IMAGE_3":$CI_COMMIT_TAG
-    - docker push "$IMAGE_3":latest
     - docker push "$IMAGE_4":$CI_COMMIT_TAG
-    - docker push "$IMAGE_4":latest
     - docker push "$IMAGE_5":$CI_COMMIT_TAG
-    - docker push "$IMAGE_5":latest
     - docker push "$IMAGE_6":$CI_COMMIT_TAG
-    - docker push "$IMAGE_6":latest
   only:
     - tags
-build-staging:
+build-master-staging:
   image: docker:latest
   stage: build
   services:
@@ -54,34 +48,32 @@ build-staging:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
+    - if [[ "$CI_COMMIT_BRANCH" = "master" ]] ; then TAG_USED="latest"; else TAG_USED="staging"; fi
     - IMAGE_1="$CI_REGISTRY_IMAGE/pvs_core"
-    - docker pull "$IMAGE_1":staging || true
-    - docker build --cache-from "$IMAGE_1":staging -t "$IMAGE_1":dev -t "$IMAGE_1":staging core/
+    - docker build --cache-from "$IMAGE_1":"$TAG_USED" -t "$IMAGE_1":dev -t "$IMAGE_1":"$TAG_USED" core/
     - IMAGE_2="$CI_REGISTRY_IMAGE/pvs_preprocessor"
-    - docker pull "$IMAGE_2":staging || true
-    - docker build --cache-from "$IMAGE_2":staging -t "$IMAGE_2":dev -t "$IMAGE_2":staging preprocessor/
+    - docker build --cache-from "$IMAGE_2":"$TAG_USED" -t "$IMAGE_2":dev -t "$IMAGE_2":"$TAG_USED" preprocessor/
     - IMAGE_3="$CI_REGISTRY_IMAGE/pvs_client"
-    - docker pull "$IMAGE_3":staging || true
-    - docker build --cache-from "$IMAGE_3":staging -t "$IMAGE_3":dev -t "$IMAGE_3":staging client/
+    - docker build --cache-from "$IMAGE_3":"$TAG_USED" -t "$IMAGE_3":dev -t "$IMAGE_3":"$TAG_USED" client/
     - IMAGE_4="$CI_REGISTRY_IMAGE/pvs_cache"
-    - docker pull "$IMAGE_4":staging || true
-    - docker build --cache-from "$IMAGE_4":staging -t "$IMAGE_4":dev -t "$IMAGE_4":staging cache/
+    - docker build --cache-from "$IMAGE_4":"$TAG_USED" -t "$IMAGE_4":dev -t "$IMAGE_4":"$TAG_USED" cache/
     - IMAGE_5="$CI_REGISTRY_IMAGE/fluentd"
-    - docker pull "$IMAGE_5":staging || true
-    - docker build --cache-from "$IMAGE_5":staging -t "$IMAGE_5":dev -t "$IMAGE_5":staging fluentd/
+    - docker build --cache-from "$IMAGE_5":"$TAG_USED" -t "$IMAGE_5":dev -t "$IMAGE_5":"$TAG_USED" fluentd/
     - IMAGE_6="$CI_REGISTRY_IMAGE/pvs_ingestor"
-    - docker pull "$IMAGE_6":staging || true
-    - docker build --cache-from "$IMAGE_6":staging -t "$IMAGE_6":dev -t "$IMAGE_6":staging ingestor/
+    - docker build --cache-from "$IMAGE_6":"$TAG_USED" -t "$IMAGE_6":dev -t "$IMAGE_6":"$TAG_USED" ingestor/
     - cd ./testing && ./gitlab_test.sh
     - if [ $? -ne 0 ]; then exit 1; fi  # actually fail build
-    - docker push "$IMAGE_1":staging
-    - docker push "$IMAGE_2":staging
-    - docker push "$IMAGE_3":staging
-    - docker push "$IMAGE_4":staging
-    - docker push "$IMAGE_5":staging
-    - docker push "$IMAGE_6":staging
+    - docker push "$IMAGE_1":"$TAG_USED"
+    - docker push "$IMAGE_2":"$TAG_USED"
+    - docker push "$IMAGE_3":"$TAG_USED"
+    - docker push "$IMAGE_4":"$TAG_USED"
+    - docker push "$IMAGE_5":"$TAG_USED"
+    - docker push "$IMAGE_6":"$TAG_USED"
   only:
     - staging
+    - master
+  except:
+    - tags
 build:
   image: docker:latest
   stage: build
@@ -91,25 +83,20 @@ build:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
     - IMAGE="$CI_REGISTRY_IMAGE/pvs_core"
-    - docker pull "$IMAGE":staging || true
     - docker build --cache-from "$IMAGE":staging -t "$IMAGE":dev core/
     - IMAGE="$CI_REGISTRY_IMAGE/pvs_preprocessor"
-    - docker pull "$IMAGE":staging || true
     - docker build --cache-from "$IMAGE":staging -t "$IMAGE":dev preprocessor/
     - IMAGE="$CI_REGISTRY_IMAGE/pvs_client"
-    - docker pull "$IMAGE":staging || true
     - docker build --cache-from "$IMAGE":staging -t "$IMAGE":dev client/
     - IMAGE="$CI_REGISTRY_IMAGE/pvs_cache"
-    - docker pull "$IMAGE":staging || true
     - docker build --cache-from "$IMAGE":staging -t "$IMAGE":dev cache/
     - IMAGE="$CI_REGISTRY_IMAGE/fluentd"
-    - docker pull "$IMAGE":staging || true
     - docker build --cache-from "$IMAGE":staging -t "$IMAGE":dev fluentd/
     - IMAGE="$CI_REGISTRY_IMAGE/pvs_ingestor"
-    - docker pull "$IMAGE":staging || true
     - docker build --cache-from "$IMAGE":staging -t "$IMAGE":dev ingestor/
     - cd ./testing && ./gitlab_test.sh
     - if [ $? -ne 0 ]; then exit 1; fi  # actually fail build
   except:
     - tags
     - staging
+    - master
diff --git a/README.md b/README.md
index fff3c4968fbd172317d9a8ee5f13f16fdb97adf4..768ded1929833239a707d01578f08b895ae22561 100644
--- a/README.md
+++ b/README.md
@@ -294,7 +294,6 @@ You will log in  into`/home/eox/data` directory which contains the 2 logging dir
 
  **NOTE:**  The mounted directory that you are directed into is *`/home/user`*, where `user` is the username, hence when setting / editing  the username in configs, the `sftp` mounted volumes path in `docker-compose.<collection>.yml` must change respectively.
  
-
 # Documentation
 
 ## Installation
@@ -323,6 +322,19 @@ The documentation is generated in the respective *_build/html* directory.
 
 # Create software releases
 
+## Release a new vs version
+
+We use [bump2version](https://github.com/c4urself/bump2version) to increment versions of invividual docker images and create git tags. Tags after push trigger CI `docker push` action of versioned images. It also updates used image versions in `.ops` docker compose files.
+Pushing to `master` branch updates `latest` images, while `staging` branch push updates `staging` images.
+For **Versions* in general, we use semantic versioning with format {major}.{minor}.{patch}-{release}.{build}.
+First check deployed staging version on staging platform (TBD), then if no problems are found, proceed.
+Following operation should be done on `staging` branch.
+```
+bump2version <major/minor/patch/release/build>
+git push
+git push --tags
+```
+Then `staging` branch should be merged to `master`, unless only a patch to previous versions is made.
 ## Source code release
 
 Create a TAR from source code: