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 $@