diff --git a/.env b/.env new file mode 100644 index 0000000..a73747c --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +SERVICE_PORT=9880 +USER_VOLUME=./user-volume +DATA_VOLUME=./data-volume diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2f93719 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,107 @@ +ARG ROOT_CONTAINER=quay.io/cdis/ubuntu:focal + +FROM $ROOT_CONTAINER + +LABEL maintainer="Jupyter Project " + +# Fix DL4006 +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +USER root + +# Install all OS dependencies for the notebook server that starts but lacks all +# features (e.g., download as all possible file formats) +ENV DEBIAN_FRONTEND noninteractive +RUN apt-get update --yes && \ + apt-get install --yes --no-install-recommends \ + python3.9 \ + python3-pip \ + tini \ + wget \ + git \ + curl \ + ca-certificates \ + sudo \ + locales \ + # fonts-liberation \ + # vim \ + run-one && \ + apt-get clean && rm -rf /var/lib/apt/lists/* && \ + echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \ + locale-gen + +# Set Python 3.9 as the default Python version +RUN ln -s /usr/bin/python3.9 /usr/bin/python + +# Add the Python 3.9 executable path to the PATH environment variable +ENV PATH="/usr/bin/python3.9:$PATH" + +# Upgrade pip to ensure it's associated with Python 3.9.5 +RUN python3.9 -m pip install --upgrade pip + +# Remove /usr/bin/pip3 if it exists +RUN rm -f /usr/bin/pip3 + +# Create a symbolic link from pip3 to pip +RUN ln -s /usr/bin/pip /usr/bin/pip3 + +RUN pip install JPype1 jupyter + +RUN jupyter notebook --generate-config + +# step 1 to disable downloads: +RUN jupyter labextension disable @jupyterlab/docmanager-extension:download \ + && jupyter labextension disable @jupyterlab/filebrowser-extension:download + +RUN pip install pandas numpy seaborn scipy matplotlib pyNetLogo SALib boto3 awscli --upgrade +RUN pip install gen3==4.18.0 --upgrade +RUN pip install jupyter --upgrade +# step 2 to disable downloads: +RUN pip uninstall nbconvert --yes +# step 3 to install packages: +RUN pip install tensorflow[and-cuda]==2.14.0 +RUN pip install torch==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 --index-url https://download.pytorch.org/whl/cu118 + +# Create a non-root user for Jupyter without copying /bin or /bin/bash +ARG NB_USER=jovyan +ARG NB_UID=1000 +ARG NB_GID=100 +RUN useradd -m -s /bin/bash -N -u $NB_UID $NB_USER && \ + chown -R $NB_USER:users /home/$NB_USER && \ + chmod -R u+rwx /home/$NB_USER && \ + mkdir -p /home/$NB_USER/pd + +# Configure environment +ENV CONDA_DIR=/opt/conda \ + PATH=/usr/local/bin:$PATH \ + SHELL=/bin/bash \ + NB_USER=${NB_USER} \ + NB_UID=${NB_UID} \ + NB_GID=${NB_GID} \ + HOME=/home/$NB_USER \ + LC_ALL=en_US.UTF-8 \ + LANG=en_US.UTF-8 \ + LANGUAGE=en_US.UTF-8 + +# Expose port 8888 for JupyterLab +EXPOSE 8888 + +# Add local files as late as possible to avoid cache busting +RUN wget https://raw.githubusercontent.com/jupyter/docker-stacks/7e1a19a8427f99652c75d1d4fda3df780721b574/images/docker-stacks-foundation/fix-permissions +RUN mv fix-permissions /usr/local/bin/fix-permissions.sh +COPY start.sh /usr/local/bin/ +COPY start-notebook.sh /usr/local/bin/ +COPY start-singleuser.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/*.sh + +COPY resources/custom.js /home/$NB_USER/.jupyter/custom/ +COPY resources/jupyter_notebook_config.py /home/$NB_USER/.jupyter/tmp.py +RUN cat /home/$NB_USER/.jupyter/tmp.py >> /home/$NB_USER/.jupyter/jupyter_notebook_config.py && rm /home/$NB_USER/.jupyter/tmp.py + +RUN fix-permissions.sh "/home/${NB_USER}" + +USER $NB_USER + +# Set the default command to start JupyterLab +WORKDIR /home/$NB_USER +ENTRYPOINT ["jupyter", "lab", "--allow-root", "--ip=0.0.0.0", "--port=8888", "--no-browser"] diff --git a/README.md b/README.md index 7439973..28da981 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ -# bridge2ai-jupyter -Docker Image for JupyterHub with restricted download and tensorflow/pytorch +# Bridge2AI Jupyter + +an adapted JupyterHub image of https://github.com/uc-cdis/containers/blob/master/jupyter-restricted-download/ with pytorch and tensorflow installed \ No newline at end of file diff --git a/resources/custom.js b/resources/custom.js new file mode 100644 index 0000000..2f6d4c1 --- /dev/null +++ b/resources/custom.js @@ -0,0 +1,3 @@ +define(['base/js/namespace'], function(Jupyter){ + Jupyter._target = '_self'; +}) diff --git a/resources/jupyter_notebook_config.py b/resources/jupyter_notebook_config.py new file mode 100644 index 0000000..89d1b20 --- /dev/null +++ b/resources/jupyter_notebook_config.py @@ -0,0 +1,3 @@ +c.NotebookApp.tornado_settings = { + "headers": {"Content-Security-Policy": "frame-ancestors 'self'"} +} diff --git a/start-notebook.sh b/start-notebook.sh new file mode 100644 index 0000000..d028cfd --- /dev/null +++ b/start-notebook.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + +set -e + +. /usr/local/bin/start.sh jupyter notebook --no-browser --port 8888 --ip=* --NotebookApp.token='' --NotebookApp.disable_check_xsrf=True $* diff --git a/start-singleuser.sh b/start-singleuser.sh new file mode 100644 index 0000000..09c1d69 --- /dev/null +++ b/start-singleuser.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + +set -e + +# set default ip to 0.0.0.0 +if [[ "$NOTEBOOK_ARGS $@" != *"--ip="* ]]; then + NOTEBOOK_ARGS="--ip=0.0.0.0 $NOTEBOOK_ARGS" +fi + +# handle some deprecated environment variables +# from DockerSpawner < 0.8. +# These won't be passed from DockerSpawner 0.9, +# so avoid specifying --arg=empty-string +if [ ! -z "$NOTEBOOK_DIR" ]; then + NOTEBOOK_ARGS="--notebook-dir='$NOTEBOOK_DIR' $NOTEBOOK_ARGS" +fi +if [ ! -z "$JPY_PORT" ]; then + NOTEBOOK_ARGS="--port=$JPY_PORT $NOTEBOOK_ARGS" +fi +if [ ! -z "$JPY_USER" ]; then + NOTEBOOK_ARGS="--user=$JPY_USER $NOTEBOOK_ARGS" +fi +if [ ! -z "$JPY_COOKIE_NAME" ]; then + NOTEBOOK_ARGS="--cookie-name=$JPY_COOKIE_NAME $NOTEBOOK_ARGS" +fi +if [ ! -z "$JPY_BASE_URL" ]; then + NOTEBOOK_ARGS="--base-url=$JPY_BASE_URL $NOTEBOOK_ARGS" +fi +if [ ! -z "$JPY_HUB_PREFIX" ]; then + NOTEBOOK_ARGS="--hub-prefix=$JPY_HUB_PREFIX $NOTEBOOK_ARGS" +fi +if [ ! -z "$JPY_HUB_API_URL" ]; then + NOTEBOOK_ARGS="--hub-api-url=$JPY_HUB_API_URL $NOTEBOOK_ARGS" +fi +if [ ! -z "$JUPYTER_ENABLE_LAB" ]; then + NOTEBOOK_BIN="jupyter labhub" +else + NOTEBOOK_BIN=jupyterhub-singleuser +fi + +. /usr/local/bin/start.sh $NOTEBOOK_BIN $NOTEBOOK_ARGS $@ diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..f3c3a67 --- /dev/null +++ b/start.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright (c) Jupyter Development Team. +# Distributed under the terms of the Modified BSD License. + +set -e + +# Handle special flags if we're root +if [ $UID == 0 ] ; then + # Change UID of NB_USER to NB_UID if it does not match + if [ "$NB_UID" != $(id -u $NB_USER) ] ; then + usermod -u $NB_UID $NB_USER + chown -R $NB_UID $CONDA_DIR . + fi + + # Enable sudo if requested + if [ ! -z "$GRANT_SUDO" ]; then + echo "$NB_USER ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/notebook #pragma: allowlist secret + fi + + # Exec the command as NB_USER + exec su $NB_USER -c "env PATH=$PATH $*" +else + # Exec the command + exec $* +fi