diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 198c7c306385da123f4ebaff0b3914dd2442ab29..e4688ce940240259bb27bbfe53d926a0b1b62cf4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,15 +1,16 @@
 variables:
   docker_registry_user: "robot$$gitlab"
-  docker_image_tag: "1.5"
 
 stages:
   - build
 
-build_base:
+build_image:
   stage: build
   script:
-    - docker build -f base/Dockerfile -t docker-registry.ebrains.eu/clb-jupyter-image/base:$docker_image_tag .
+    - docker build -f base/Dockerfile -t docker-registry.ebrains.eu/clb-jupyter-image/ebrains:$CI_COMMIT_TAG .
     - docker login -u $docker_registry_user -p $docker_registry_prod_token docker-registry.ebrains.eu
-    - docker push docker-registry.ebrains.eu/clb-jupyter-image/base:$docker_image_tag
+    - docker push docker-registry.ebrains.eu/clb-jupyter-image/ebrains:$CI_COMMIT_TAG
+  only:
+    - tags
   tags:
     - shell-runner
diff --git a/base/Dockerfile b/base/Dockerfile
index b718930f06053f6e17971cea46812496d5a652bc..00fbb5ec855a5834741a935a5853fc04dc369dd3 100644
--- a/base/Dockerfile
+++ b/base/Dockerfile
@@ -1,112 +1,120 @@
-FROM centos/python-36-centos7
+FROM ubuntu:focal
 
-MAINTAINER Collaboratory Platform <platform@humanbrainproject.eu>
+LABEL maintainer="Collaboratory Platform <platform@humanbrainproject.eu>"
+
+ARG NB_USER="jovyan"
+ARG NB_UID=1000
+ARG NB_GID=100
 
 ENV GIT_COMMITTER_NAME=platform@humanbrainproject.eu \
     GIT_COMMITTER_EMAIL=platform@humanbrainproject.eu \
+    USER="${NB_USER}" \
     MPLBACKEND=Agg \
-    SDAHOME=/opt/app-root/lib/sda_flex \
-    MPICC=/usr/lib64/mpich/bin/mpicc \
+    SHELL=/bin/bash \
     XDG_CACHE_HOME=/tmp/cache/ \
-    LAB_IMAGE_NAME=EBRAINS_EXPERIMENTAL
+    LAB_IMAGE_NAME=EBRAINS_OFFICIAL
 
 USER root
 
-# the version of jupyter lab isn't compatible with newer node versions. Specify version of node (10)
-RUN curl -SsL https://rpm.nodesource.com/setup_10.x | bash
-
-# Install all OS dependencies for notebook server that starts but lacks all
-# features (e.g., download as all possible file formats)
-# to use devtoolset 10 (e.g. gcc): scl enable devtoolset-10 bash
-RUN yum install -y epel-release && \
-        yum-config-manager --enable epel && \
-        yum  groupinstall -y 'Development Tools' && \
-        yum install -y centos-release-scl && yum install -y devtoolset-10 && \
-        yum install -y \
-        bzip2-devel \
-        cmake \
-        cmake3 \
-        csh \
-        curl \
-        Cython \
-        fio \
-        freetype-devel \
-        gsl-devel \
-        hdf5-devel \
-        liberation-fonts \
-        libtool-ltdl-devel \
-        libXext-devel \
-        libXrender \
-        llvm \
-        lsof \
-        mpich \
-        mpich-devel \
-        ncurses-devel \
-        nodejs \
-        pandoc \
-        python-devel \
-        R \
-        readline-devel \
-        texlive-latex \
-        unzip \
-        vim \
-        wget \
-        && yum  -y clean all
-
-# Set the Switzerland timezone
+# Set the Switzerland timezone (necessary to make r-base install noninteractive)
 RUN ln -sf /usr/share/zoneinfo/Europe/Zurich /etc/localtime
 
-RUN mkdir -p /opt/app-root/etc /opt/app-root/clb/
+# Set to noninteractive for install
+ENV DEBIAN_FRONTEND noninteractive
+RUN apt-get update --yes && \
+    apt-get install --yes \
+    ca-certificates \
+    cmake \
+    csh \
+    curl \
+    cython \
+    gcc \
+    gettext \
+    git \
+    libnss-wrapper \
+    llvm \
+    lsof \
+    mpich \
+    pandoc \
+    python3-pip \
+    r-base \
+    unzip \
+    vim  && \
+    apt-get clean && rm -rf /var/lib/apt/lists/*
+
+# install nodejs
+RUN curl -fsSL https://deb.nodesource.com/setup_17.x | bash
+RUN apt-get install -y nodejs
+
+# install min texlive (necessary for nb exports)
+RUN apt-get update --yes && \
+    apt-get install --yes --no-install-recommends \
+    texlive-xetex \
+    texlive-fonts-recommended \
+    texlive-plain-generic && \
+    apt-get clean && rm -rf /var/lib/apt/lists/*
+
+# jupyter install in /opt/app-root/ for legacy reasons (previously based on centos base image)
+RUN mkdir -p /opt/app-root/etc /opt/app-root/clb/ /opt/app-root/src
 COPY base/jupyter_notebook_config.py /opt/app-root/etc/
+
+# folders for drive integration
+RUN mkdir -p /mnt/user/
 RUN ln -s /mnt/user/drive /opt/app-root/src/drive
 RUN ln -s /mnt/user/shared /opt/app-root/src/shared
 
+ENV HOME=/opt/app-root/src/
 
+# install pip packages
 COPY base/requirements.txt /tmp
-# needs to be installed before rpy2
-RUN pip install cffi==1.14.5
-RUN pip install -r /tmp/requirements.txt
-# requirements.tvb need to be installed in separate step
-COPY base/requirements.tvb.txt /tmp
-RUN pip install -r /tmp/requirements.tvb.txt
-
-RUN python -c "import matplotlib.pyplot"
-
-RUN jupyter nbextension enable --py widgetsnbextension --sys-prefix && \
-        jupyter nbextension enable --py nglview --sys-prefix
+RUN pip install --no-cache-dir -r /tmp/requirements.txt
 
-RUN jupyter labextension disable @jupyterlab/filebrowser-extension:share-file
+# fix missing template issue in nbgitpuller: https://github.com/jupyterhub/nbgitpuller/issues/235
+# remove this once it has been fixed in project
+RUN ln -s /usr/local/lib/python3.8/dist-packages/nbgitpuller/templates/status.html /usr/local/lib/python3.8/dist-packages/notebook/templates/
 
-# todo: investigate issue why labextension install fails with an npm error
-RUN jupyter labextension install --no-build @jupyter-widgets/jupyterlab-manager@1.1.0 \
-                             @bokeh/jupyter_bokeh@1.2.0 \
-                             @krassowski/jupyterlab_go_to_definition@0.7.1 \
-                             jupyterlab-topbar-extension@0.4.0 \
-                             jupyterlab-system-monitor@0.4.1 \
-                             jupyterlab-plotly@4.14.3 \
-                             nglview-js-widgets@2.7.1 \
-                             clb-jupyter-ext-copy-shareable-link@1.0.0 \
-                             clb-jupyter-ext-query-params@1.0.1
+# disable ipcluster extension
+RUN jupyter labextension disable ipcluster \
+                              ipyparallel-labextension
 
-RUN jupyter labextension install jupyter-matplotlib@0.7.4
+# install additional labextensions
+RUN jupyter labextension install --no-build @jupyter-widgets/jupyterlab-manager@v3.0.1 \
+                             @krassowski/jupyterlab_go_to_definition@v1.0.0 \
+                             jupyterlab-topbar-extension@v0.6.0 \
+                             jupyterlab-system-monitor@v0.7.0 \
+                             jupyterlab-plotly@v5.5.0 \
+                             jupyter-matplotlib@v0.10.4 \
+                             clb-jupyter-ext-query-params@3.2.0
 
 RUN jupyter lab build
 
 RUN jupyter notebook --generate-config
-RUN mkdir -p /opt/app-root/src/.ipython/profile_default/startup/
-RUN mkdir -p /tmp/cache/
-
-# @TODO Remove this when bug is fixed: https://github.com/ipython/ipython/issues/11546
-RUN echo 'c.Completer.use_jedi = False' >> /opt/app-root/src/.ipython/profile_default/ipython_config.py
+RUN mkdir -p /opt/app-root/src/.ipython/profile_default/startup/ /opt/app-root/src/.local/lib/python3.8/site-packages/ /tmp/cache/
 
 # Preload clb_oauth
 RUN echo 'from clb_nb_utils import oauth as clb_oauth' >> /opt/app-root/src/.ipython/profile_default/startup/50-clb-nb-utils.py
 
-RUN fix-permissions /opt/app-root
-RUN fix-permissions /tmp/cache
+# fix permissions so NB_USER has permissions to run notebooks and install packages
+COPY base/fix-permissions /usr/local/bin/fix-permissions
+RUN chmod +x /usr/local/bin/fix-permissions
+
+RUN fix-permissions /opt/app-root/ && \
+    fix-permissions /tmp/cache/ && \
+    fix-permissions /usr/local/share/jupyter/ && \
+    fix-permissions /usr/local/etc/jupyter && \
+    fix-permissions /usr/etc/jupyter/
+
+# to support OpenShift's arbitrary UIDs
+# more info: https://docs.openshift.com/enterprise/3.1/creating_images/guidelines.html
+COPY base/passwd.template /tmp/passwd.template
+COPY base/group.template /tmp/group.template
+COPY base/start-notebook.sh /opt/app-root/etc/
+RUN chmod +x /opt/app-root/etc/start-notebook.sh
+
+WORKDIR /opt/app-root/src/
 
 EXPOSE 8080
 
-USER 1000
+USER ${NB_UID}
 
-CMD jupyter labhub --NotebookApp.default_url=/lab --config=/opt/app-root/etc/jupyter_notebook_config.py $@
+CMD /opt/app-root/etc/start-notebook.sh
diff --git a/base/fix-permissions b/base/fix-permissions
new file mode 100644
index 0000000000000000000000000000000000000000..45354c0dccbadfef143fc32333a8b240430d3d89
--- /dev/null
+++ b/base/fix-permissions
@@ -0,0 +1,28 @@
+#!/bin/sh
+# source: https://github.com/sclorg/s2i-base-container/blob/master/core/root/usr/bin/fix-permissions
+
+# Allow this script to fail without failing a build
+set +e
+
+SYMLINK_OPT=${2:--L}
+
+# Fix permissions on the given directory or file to allow group read/write of
+# regular files and execute of directories.
+
+[ $(id -u) -ne 0 ] && CHECK_OWNER=" -uid $(id -u)"
+
+# If argument does not exist, script will still exit with 0,
+# but at least we'll see something went wrong in the log
+if ! [ -e "$1" ] ; then
+  echo "ERROR: File or directory $1 does not exist." >&2
+  # We still want to end successfully
+  exit 0
+fi
+
+find $SYMLINK_OPT "$1" ${CHECK_OWNER} \! -gid 0 -exec chgrp 0 {} +
+find $SYMLINK_OPT "$1" ${CHECK_OWNER} \! -perm -g+rw -exec chmod g+rw {} +
+find $SYMLINK_OPT "$1" ${CHECK_OWNER} -perm /u+x -a \! -perm /g+x -exec chmod g+x {} +
+find $SYMLINK_OPT "$1" ${CHECK_OWNER} -type d \! -perm /g+x -exec chmod g+x {} +
+
+# Always end successfully
+exit 0
\ No newline at end of file
diff --git a/base/group.template b/base/group.template
new file mode 100644
index 0000000000000000000000000000000000000000..a957d0695246d100aae8a5ed23b5922d2688f361
--- /dev/null
+++ b/base/group.template
@@ -0,0 +1,2 @@
+nb_group:x:${GROUP_ID}:
+nb_group_user:x:${USER_ID}:
\ No newline at end of file
diff --git a/base/jupyter_notebook_config.py b/base/jupyter_notebook_config.py
index d82e2241d473dd29b7cf8f656eea90e6629abf76..6b9fc72094b87c9749d64cced15572d7fb6a21ac 100644
--- a/base/jupyter_notebook_config.py
+++ b/base/jupyter_notebook_config.py
@@ -7,7 +7,6 @@ c.NotebookApp.port = port
 c.NotebookApp.open_browser = False
 c.NotebookApp.quit_button = False
 
-c.PDFExporter.enabled = False
 c.WebPDFExporter.enabled = False
 
 if os.environ.get('JUPYTERHUB_SERVICE_PREFIX'):
diff --git a/base/passwd.template b/base/passwd.template
new file mode 100644
index 0000000000000000000000000000000000000000..bb42cf7afc363193bab1ddbab51a1d8b76341105
--- /dev/null
+++ b/base/passwd.template
@@ -0,0 +1,14 @@
+root:x:0:0:root:/root:/bin/bash
+bin:x:1:1:bin:/bin:/sbin/nologin
+daemon:x:2:2:daemon:/sbin:/sbin/nologin
+adm:x:3:4:adm:/var/adm:/sbin/nologin
+lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
+sync:x:5:0:sync:/sbin:/bin/sync
+shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
+halt:x:7:0:halt:/sbin:/sbin/halt
+mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
+operator:x:11:0:operator:/root:/sbin/nologin
+games:x:12:100:games:/usr/games:/sbin/nologin
+ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
+nobody:x:99:99:Nobody:/:/sbin/nologin
+${USER}:x:${USER_ID}:${GROUP_ID}:${USER_DESCRIPTION}:${HOME}:/bin/bash
\ No newline at end of file
diff --git a/base/requirements.tvb.txt b/base/requirements.tvb.txt
deleted file mode 100644
index 1e3a06834e52f63f7f592a1b519bf2c68cd8ba8e..0000000000000000000000000000000000000000
--- a/base/requirements.tvb.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-gdist==1.0.3
-tvb-library==2.0
\ No newline at end of file
diff --git a/base/requirements.txt b/base/requirements.txt
index 3de215cdde9051b62abaa26b000d94c432a28bfe..f4e10a51dbfa23adc3ef44ba67e80222e4231c70 100644
--- a/base/requirements.txt
+++ b/base/requirements.txt
@@ -1,45 +1,49 @@
-beautifulsoup4==4.8.2
-bluepyopt==1.9.12
-bokeh==1.4.0
-Cython==0.29.15
-cryptography==3.3.2
-elephant==0.6.4
-h5py==2.10.0
-ipympl==0.5.8
-ipywidgets==7.5.1
-jupyterhub==1.1.0
-jupyterlab==1.2.6
-jupyterlab-git==0.9.0
-lazyarray==0.3.3
-lxml==4.5.0
-matplotlib==3.3.1
-mpi4py==3.0.3
-nbdime==1.1.0
-nbgitpuller==0.9.0
-nbresuse==0.3.3
-neo==0.8.0
-neurom==1.4.14
-nglview==2.7.1
-nibabel==3.0.1
-numba==0.48.0
-numexpr==2.7.1
-numpy==1.18.1
-pandas==1.0.1
-patsy==0.5.1
-plotly==4.5.1
-python-swiftclient==3.9.0
-PyJWT==1.7.1
-pyunicore==0.5.7
+beautifulsoup4==4.10.0
+bluepyopt==1.11.5
+bokeh==2.4.2
+Cython==0.29.26
+cffi==1.14.5
+cryptography==36.0.1
+elephant==0.10.0
+h5py==3.6.0
+ipympl==0.8.5
+ipywidgets==7.6.5
+jupyterhub==1.5.0
+jupyterlab==3.2.8
+jupyterlab-git==0.34.1
+lazyarray==0.5.1
+lxml==4.7.1
+matplotlib==3.5.1
+mpi4py==3.1.3
+nbdime==3.1.1
+nbgitpuller==1.0.2
+nbresuse==0.4.0
+neo==0.10.0
+neurom==3.1.0
+nglview==3.0.3
+nibabel==3.2.1
+numba==0.54.1
+numexpr==2.8.1
+numpy==1.20.3
+pandas==1.3.5
+patsy==0.5.2
+plotly==5.5.0
+Pygments==2.11.2
+python-swiftclient==3.13.0
+PyJWT==2.3.0
+pyunicore==0.9.13
 requests-oauthlib==1.3.0
-rise==5.6.1
+rise==5.7.1
 rpy2==3.4.5
-scikit-image==0.16.2
-scikit-learn==0.22.1
-scipy==1.4.1
-seaborn==0.10.0
-statsmodels==0.11.1
-sympy==1.5.1
+scikit-image==0.19.1
+scikit-learn==1.0.2
+scipy==1.7.3
+seaborn==0.11.2
+statsmodels==0.13.1
+sympy==1.9
 vincent==0.4.4
-widgetsnbextension==3.5.1
-xlrd==1.2.0
+widgetsnbextension==3.5.2
+xlrd==2.0.1
 git+https://github.com/HumanBrainProject/clb-nb-utils.git
+# fix issue with nbconvert in jupyter_server version installed by jupyterlab dependency (remove once fixed in offical release)
+git+https://github.com/jupyter-server/jupyter_server.git@d2015290b80bfdaa6ebb990cdccc0155921696f5
\ No newline at end of file
diff --git a/base/start-notebook.sh b/base/start-notebook.sh
new file mode 100644
index 0000000000000000000000000000000000000000..028dbe57c849c0fc3d51451c0e4b8e603c048d9a
--- /dev/null
+++ b/base/start-notebook.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -e
+# to support OpenShift's arbitrary UIDs
+# more info: https://docs.openshift.com/enterprise/3.1/creating_images/guidelines.html
+export USER_ID=$(id -u)
+export GROUP_ID=$(id -g)
+export USER_DESCRIPTION="Notebook User"
+envsubst < /tmp/passwd.template > /tmp/passwd
+envsubst < /tmp/group.template > /tmp/group
+export LD_PRELOAD=libnss_wrapper.so
+export NSS_WRAPPER_PASSWD=/tmp/passwd
+export NSS_WRAPPER_GROUP=/tmp/group
+exec jupyter labhub --NotebookApp.default_url=/lab --config=/opt/app-root/etc/jupyter_notebook_config.py $@