diff --git a/common_requirements.in b/common_requirements.in
index 2616cf85133f9f4e623f9a5c7f9e91a02083b2e3..8a027cfbd1ecf8bf4adc535dd9d5e3a769a2f2f8 100644
--- a/common_requirements.in
+++ b/common_requirements.in
@@ -1,8 +1,8 @@
 coverage==6.3
-grpcio==1.43.0
-grpcio-health-checking==1.43.0
-grpcio-tools==1.43.0
+grpcio==1.47.*
+grpcio-health-checking==1.47.*
+grpcio-tools==1.47.*
 prometheus-client==0.13.0
-protobuf==3.19.3
+protobuf==3.20.*
 pytest==6.2.5
 pytest-benchmark==3.4.1
diff --git a/src/context/.gitlab-ci.yml b/src/context/.gitlab-ci.yml
index 7a58fee17d7ac1e6b45235bfe2d3f3c7865bc80b..166cca978e8b5d7715779092b75803aba90cf9ea 100644
--- a/src/context/.gitlab-ci.yml
+++ b/src/context/.gitlab-ci.yml
@@ -55,8 +55,8 @@ unit test context:
     - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
     - docker pull "redis:6.2"
     - docker run --name redis -d --network=teraflowbridge redis:6.2
-    - docker run --name $IMAGE_NAME -d -p 1010:1010 --env "DB_BACKEND=redis" --env "REDIS_SERVICE_HOST=redis" --env "REDIS_SERVICE_PORT=6379" --env "REDIS_DATABASE_ID=0" -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
     - sleep 10
+    - docker run --name $IMAGE_NAME -d -p 1010:1010 --env "DB_BACKEND=redis" --env "REDIS_SERVICE_HOST=redis" --env "REDIS_SERVICE_PORT=6379" --env "REDIS_DATABASE_ID=0" -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
     - docker ps -a
     - docker logs $IMAGE_NAME
     - docker exec -i $IMAGE_NAME bash -c "coverage run -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/opt/results/${IMAGE_NAME}_report.xml"
diff --git a/src/device/requirements.in b/src/device/requirements.in
index e736c743d973d5a8b7e659b690f2aaad45490f40..e5aaddecb4901da55a411d83c8c1df26f8d47069 100644
--- a/src/device/requirements.in
+++ b/src/device/requirements.in
@@ -11,3 +11,9 @@ pytz==2021.3
 redis==4.1.2
 requests==2.27.1
 xmltodict==0.12.0
+
+# pip's dependency resolver does not take into account installed packages.
+# p4runtime does not specify the version of grpcio/protobuf it needs, so it tries to install latest one
+# adding here again grpcio==1.47.* and protobuf==3.20.* with explicit versions to prevent collisions
+grpcio==1.47.*
+protobuf==3.20.*
diff --git a/src/monitoring/.gitlab-ci.yml b/src/monitoring/.gitlab-ci.yml
index 61aec5fb3b29b40bc413a5d9a6452086d0005dce..69337996af00f724fc48d6b6749a4ba6f0a56dff 100644
--- a/src/monitoring/.gitlab-ci.yml
+++ b/src/monitoring/.gitlab-ci.yml
@@ -21,7 +21,7 @@ build monitoring:
   before_script:
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
   script:
-    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile ./src/
+    - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile .
     - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
     - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
   after_script:
@@ -30,6 +30,8 @@ build monitoring:
     - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
     - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' 
     - changes:
+      - src/common/**/*.py
+      - proto/*.proto
       - src/$IMAGE_NAME/**/*.{py,in,yml}
       - src/$IMAGE_NAME/Dockerfile
       - src/$IMAGE_NAME/tests/*.py
@@ -51,9 +53,10 @@ unit test monitoring:
     - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi
   script:
     - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG"
-    - docker run --name influxdb -d -p 8086:8086 -e INFLUXDB_DB=$INFLUXDB_DATABASE -e INFLUXDB_ADMIN_USER=$INFLUXDB_USER -e INFLUXDB_ADMIN_PASSWORD=$INFLUXDB_PASSWORD -e INFLUXDB_HTTP_AUTH_ENABLED=True --network=teraflowbridge --rm influxdb:1.8
+    - docker pull "influxdb:1.8"
+    - docker run --name influxdb -d -p 8086:8086 -e INFLUXDB_DB=$INFLUXDB_DATABASE -e INFLUXDB_ADMIN_USER=$INFLUXDB_USER -e INFLUXDB_ADMIN_PASSWORD=$INFLUXDB_PASSWORD -e INFLUXDB_HTTP_AUTH_ENABLED=True --network=teraflowbridge influxdb:1.8
     - sleep 10
-    - docker run --name $IMAGE_NAME -d -p 7070:7070 --env INFLUXDB_USER=$INFLUXDB_USER --env INFLUXDB_PASSWORD=$INFLUXDB_PASSWORD --env INFLUXDB_DATABASE=$INFLUXDB_DATABASE --env INFLUXDB_HOSTNAME=influxdb --env INFLUXDB_PORT=8086 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge --rm $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
+    - docker run --name $IMAGE_NAME -d -p 7070:7070 --env INFLUXDB_USER=$INFLUXDB_USER --env INFLUXDB_PASSWORD=$INFLUXDB_PASSWORD --env INFLUXDB_DATABASE=$INFLUXDB_DATABASE --env INFLUXDB_HOSTNAME=influxdb --env INFLUXDB_PORT=8086 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG
     - sleep 30
     - docker ps -a
     - docker logs $IMAGE_NAME
@@ -68,6 +71,8 @@ unit test monitoring:
     - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)'
     - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' 
     - changes:
+      - src/common/**/*.py
+      - proto/*.proto
       - src/$IMAGE_NAME/**/*.{py,in,yml}
       - src/$IMAGE_NAME/Dockerfile
       - src/$IMAGE_NAME/tests/*.py
@@ -78,7 +83,7 @@ unit test monitoring:
       when: always
       reports:
         junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml
- 
+
 # Deployment of the service in Kubernetes Cluster
 deploy monitoring:
   variables:
diff --git a/src/monitoring/Dockerfile b/src/monitoring/Dockerfile
index ca18929f18816176a503126f43514b7ef32a3a12..f26741df048572339ee757c7dce8b89604558caf 100644
--- a/src/monitoring/Dockerfile
+++ b/src/monitoring/Dockerfile
@@ -12,50 +12,59 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM python:3-slim
+FROM python:3.9-slim
 
 # Install dependencies
 RUN apt-get --yes --quiet --quiet update && \
     apt-get --yes --quiet --quiet install wget g++ && \
     rm -rf /var/lib/apt/lists/*
 
-# show python logs as they occur
+# Set Python to show logs as they occur
 ENV PYTHONUNBUFFERED=0
 
-# download the grpc health probe
+# Download the gRPC health probe
 RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
     wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
     chmod +x /bin/grpc_health_probe
 
 # Get generic Python packages
-RUN python3 -m pip install --upgrade pip setuptools wheel pip-tools
+RUN python3 -m pip install --upgrade pip
+RUN python3 -m pip install --upgrade setuptools wheel
+RUN python3 -m pip install --upgrade pip-tools
 
-# Set working directory
+# Get common Python packages
+# Note: this step enables sharing the previous Docker build steps among all the Python components
 WORKDIR /var/teraflow
+COPY common_requirements.in common_requirements.in
+RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in
+RUN python3 -m pip install -r common_requirements.txt
 
-# Create module sub-folders
+# Add common files into working directory
+WORKDIR /var/teraflow/common
+COPY src/common/. ./
+RUN rm -rf proto
+
+# Create proto sub-folder, copy .proto files, and generate Python code
+RUN mkdir -p /var/teraflow/common/proto
+WORKDIR /var/teraflow/common/proto
+RUN touch __init__.py
+COPY proto/*.proto ./
+RUN python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. *.proto
+RUN rm *.proto
+RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \;
+
+# Create component sub-folders, get specific Python packages
 RUN mkdir -p /var/teraflow/monitoring
-RUN mkdir -p /var/teraflow/common
-RUN mkdir -p /var/teraflow/common/tools
-RUN mkdir -p /var/teraflow/common/rpc_method_wrapper
-RUN mkdir -p /var/teraflow/device
-RUN mkdir -p /var/teraflow/context
-
-# Get Python packages per module
-COPY monitoring/requirements.in requirements.in
-RUN pip-compile --output-file=requirements.txt requirements.in
+WORKDIR /var/teraflow/monitoring
+COPY src/monitoring/requirements.in requirements.in
+RUN pip-compile --quiet --output-file=requirements.txt requirements.in
 RUN python3 -m pip install -r requirements.txt
 
-# add files into working directory
-COPY monitoring/. monitoring
-COPY common/. common
-COPY context/. context
-COPY device/. device
-
-RUN rm -r common/message_broker/tests
-RUN rm -r common/orm/tests
-RUN rm -r common/rpc_method_wrapper/tests
-RUN rm -r context/tests/test_unitary.py
+# Add component files into working directory
+WORKDIR /var/teraflow
+COPY src/context/. context/
+COPY src/device/. device/
+COPY src/monitoring/. monitoring/
 
+# Start the service
 ENTRYPOINT ["python", "-m", "monitoring.service"]
-
diff --git a/src/monitoring/requirements.in b/src/monitoring/requirements.in
index 4d4f057bdc6b66d699ef1e723b64c05d60f5cc0e..1b5459e32c326893f89df02bd1c96fb459577a36 100644
--- a/src/monitoring/requirements.in
+++ b/src/monitoring/requirements.in
@@ -1,8 +1,6 @@
 anytree==2.8.0
 APScheduler==3.8.1
 fastcache==1.1.0
-grpcio==1.43.0
-grpcio-health-checking==1.43.0
 #google-api-core
 #opencensus[stackdriver]
 #google-cloud-profiler
@@ -11,10 +9,6 @@ Jinja2==3.0.3
 ncclient==0.6.13
 p4runtime==1.3.0
 paramiko==2.9.2
-prometheus-client==0.13.0
-protobuf==3.19.3
-pytest==6.2.5
-pytest-benchmark==3.4.1
 influxdb
 python-dateutil==2.8.2
 python-json-logger==2.0.2
@@ -22,4 +16,9 @@ pytz==2021.3
 redis==4.1.2
 requests==2.27.1
 xmltodict==0.12.0
-coverage==6.3
+
+# pip's dependency resolver does not take into account installed packages.
+# p4runtime does not specify the version of grpcio/protobuf it needs, so it tries to install latest one
+# adding here again grpcio==1.47.* and protobuf==3.20.* with explicit versions to prevent collisions
+grpcio==1.47.*
+protobuf==3.20.*