Skip to content
Snippets Groups Projects
Select Git revision
  • 65766d4643c3b3e5acd276dbdb1e46bc1cee8347
  • master default protected
  • v3-modify-mail
  • snyk-fix-207483a1e839c807f95a55077e86527d
  • translations_3b5aa4f3c755059914cfa23d7d2edcde_ru
  • translations_6e4a5e377a3e50f17e6402264fdbfcc6_ru
  • translations_3b5aa4f3c755059914cfa23d7d2edcde_fa_IR
  • translations_en-yml--master_fa_IR
  • snyk-fix-7d634f2eb65555f41bf06d6af930e812
  • translations_en-yml--master_ar
  • translations_3b5aa4f3c755059914cfa23d7d2edcde_el
  • jfederico-patch-1
  • v2
  • v3
  • v1
  • release-3.1.0.2
  • release-3.1.0.1
  • release-3.1.0
  • release-2.14.8.4
  • release-3.0.9.1
  • release-3.0.9
  • release-3.0.8.1
  • release-2.14.8.3
  • release-3.0.8
  • release-3.0.7.1
  • release-2.14.8.2
  • release-3.0.7
  • release-3.0.6.1
  • release-3.0.6
  • release-3.0.5.4
  • release-3.0.5.3
  • release-2.14.8.1
  • release-3.0.5.2
  • release-3.0.5.1
  • release-3.0.5
35 results

AuthButtons.jsx

Blame
  • Dockerfile 11.22 KiB
    # syntax=docker/dockerfile:1
    
    # tensorflow-notebook:latest installs tensorflow-cpu from PyPI
    FROM quay.io/jupyter/tensorflow-notebook:latest AS build
    
    # fix: https://github.com/hadolint/hadolint/wiki/DL4006
    # fix: https://github.com/koalaman/shellcheck/wiki/SC3014
    SHELL ["/bin/bash", "-o", "pipefail", "-c"]
    
    USER root
    
    RUN apt-get update --yes && \
        apt-get install --yes --no-install-recommends \
        # general purpose utils
        git-lfs \
        htop \
        iputils-ping \
        # R pre-requisites
        fonts-dejavu \
        gcc \
        gfortran \
        r-cran-rodbc \
        unixodbc \
        unixodbc-dev && \
        apt-get clean && rm -rf /var/lib/apt/lists/*
    
    USER ${NB_UID}
    
    # R packages including IRKernel which gets installed globally.
    # r-e1071: dependency of the caret R package
    RUN mamba install --yes \
        # for VS code
        'r-languageserver' \
        'radian' \
        'r-httpgd' \
        # from Jupyter docker-stacks
        'r-base' \
        'r-caret' \
        'r-crayon' \
        'r-devtools' \
        'r-e1071' \
        'r-forecast' \
        'r-hexbin' \
        'r-htmltools' \
        'r-htmlwidgets' \
        'r-irkernel' \
        'r-nycflights13' \
        'r-randomforest' \
        'r-rcurl' \
        'r-rmarkdown' \
        'r-rodbc' \
        'r-rsqlite' \
        'r-shiny' \
        'r-tidymodels' \
        'r-tidyverse' \
        'unixodbc' && \
        mamba clean --all -f -y && \
        fix-permissions "${CONDA_DIR}" && \
        fix-permissions "/home/${NB_USER}"
    
    USER root
    
    # install code-server and extensions
    ENV CODE_VERSION=4.96.2
    RUN wget --no-hsts -q https://github.com/coder/code-server/releases/download/v$CODE_VERSION/code-server_${CODE_VERSION}_amd64.deb && \
        dpkg -i code-server_${CODE_VERSION}_amd64.deb && \
        rm -f code-server_${CODE_VERSION}_amd64.deb && \
        code-server --force \
        --install-extension ms-python.python \
        --install-extension ms-toolsai.jupyter \
        --install-extension REditorSupport.r \
        --install-extension RDebugger.r-debugger \
        --install-extension eamodio.gitlens \
        --install-extension gitlab.gitlab-workflow && \
        mkdir -p /usr/local/bin/start-notebook.d && \
        chown -R ${NB_USER} "/home/${NB_USER}/.config" "/home/${NB_USER}/.local" && \
        fix-permissions "/home/${NB_USER}"
    
    # install VS Code CLI
    RUN wget --no-hsts -q -O vscode_cli.tar.gz 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' && \
        tar -xf vscode_cli.tar.gz --directory /usr/local/bin && \
        rm vscode_cli.tar.gz && \
        chown ${NB_USER} /usr/local/bin/code && \
        fix-permissions /usr/local/bin/code
    
    # install some packages
    USER ${NB_UID}
    RUN mamba install --yes \
        # system monitor
        'bpytop' \
        # umap + hdbscan
        'umap-learn' \
        'hdbscan' \
        # gradio
        'gradio' \
        # optuna + plotly
        'optuna' \
        'plotly' \
        # optional dependencies for pandas for read_html and to support Parquet files
        'lxml' \
        'pyarrow' \
        # geopandas
        'geopandas' \
        'pysal' \
        'contextily' \
        # networkx + pyvis + netgraph
        'networkx' \
        'pyvis' \
        'netgraph' \
        # dependencies for gymnasium, install before gymnasium!
        'swig' \
        'moviepy' \
        # dependencies for jupyter-vscode-proxy (?)
        'rfc3339-validator' \
        'rfc3986-validator' \
        'uri-template' \
        'fqdn' \
        'webcolors' \
        'isoduration' \
        'jsonpointer' \
        # provide a way for lecturers to share code
        'nbgitpuller' \
        # integration of VS Code in JupyterLab
        'jupyter-server-proxy' \
        'jupyter-vscode-proxy' \
        # some improvements of jupyterlab
        'jupyterlab_execute_time' \
        'jupyter-archive' \
        'jupyterlab-git' \
        'jupyter-resource-usage' \
        # install opencv headless version
        'py-opencv=*=headless*' && \
        printf '%s\n' \
               "" \
               "# track CPU usage, prevent known bug with prometheus, set default limits if not set by MEM_LIMIT and CPU_LIMIT" \
               "import os" \
               "" \
               "c.ResourceUseDisplay.track_cpu_percent = True" \
               "c.ResourceUseDisplay.enable_prometheus_metrics = False" \
               "c.ResourceUseDisplay.mem_limit = int(os.getenv('MEM_LIMIT', os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')))" \
               "c.ResourceUseDisplay.cpu_limit = float(os.getenv('CPU_LIMIT', os.cpu_count()))" \
               >> /etc/jupyter/jupyter_notebook_config.py && \
        mamba clean --all -f -y && \
        fix-permissions "${CONDA_DIR}" && \
        fix-permissions "/home/${NB_USER}"
    
    # default settings and extensions in /etc/skel
    USER root
    # activate extensions by default
    COPY plugin.jupyterlab-settings "/home/${NB_USER}/.jupyter/lab/user-settings/@jupyterlab/extensionmanager-extension/"
    COPY plugin.jupyterlab-settings "/home/${NB_USER}/.jupyter/lab/user-settings/@jupyter-server/resource-usage/"
    RUN chown -R ${NB_USER} "/home/${NB_USER}/.jupyter" && \
        # history search with Page Up/Down
        sed -i "s/^# \(.*history-search.*\)/\1/" /etc/inputrc && \
        # VS Code Python settings
        mkdir -p "/home/${NB_USER}/.local/share/code-server/User" && \
        echo -e '{\n  "python.defaultInterpreterPath": "/opt/conda/bin/python",\n  "jupyter.sendSelectionToInteractiveWindow": true\n}' > /home/${NB_USER}/.local/share/code-server/User/settings.json && \
        mkdir -p "/home/${NB_USER}/.local/share/code-server/Machine" && \
        cp "/home/${NB_USER}/.local/share/code-server/User/settings.json" "/home/${NB_USER}/.local/share/code-server/Machine/settings.json" && \
        mkdir -p /etc/skel/.local/share/ && \
        cp -r "/home/${NB_USER}/.local/share/code-server" /etc/skel/.local/share/ && \
        # matplotlib cache
        mkdir -p /etc/skel/.cache && \
        cp -r "/home/${NB_USER}/.cache/matplotlib" /etc/skel/.cache/ && \
        # stuff
        cp -r "/home/${NB_USER}/.conda" "/home/${NB_USER}/.config" "/home/${NB_USER}/.jupyter" /etc/skel/ && \
        # VS Code extension "gitlab-workflow", default gitlab server: gitlab.cvh-server.de
        printf '%s\n' \
               '# Set default gitlab server to gitlab.cvh-server.de' \
               'relpath=".local/share/code-server/extensions/gitlab.gitlab-workflow-*/extension.js"' \
               'for abspath in /home/${NB_USER}/${relpath} /etc/skel/${relpath}; do' \
               '  if [[ -e "${abspath}" ]]; then' \
               '    sed -i "s_=\"https://gitlab.com\"_=\"https://gitlab.cvh-server.de\"_g" "${abspath}"' \
               '  fi' \
               'done' \
               >> /usr/local/bin/start-notebook.d/fix-gitlab-server.sh && \
        # source mamba.sh in bash using /etc/profile.d/conda.sh
        mamba init --system && \
        chown -R ${NB_USER} "/home/${NB_USER}/.local" && \
        fix-permissions "/home/${NB_USER}" && \
        fix-permissions "/etc/skel"
    # remember to copy back in post start hook
    
    
    # override maintainer label from Jupyter docker stacks
    LABEL maintainer="Christof Kaufmann <christof.kaufmann@hs-bochum.de>"
    # OCI annotations, see https://github.com/opencontainers/image-spec/blob/main/annotations.md
    ARG LABEL_CREATED
    ARG LABEL_REVISION=test-build
    LABEL org.opencontainers.image.created=$LABEL_CREATED
    LABEL org.opencontainers.image.authors="Christof Kaufmann <christof.kaufmann@hs-bochum.de>"
    LABEL org.opencontainers.image.source="https://gitlab.cvh-server.de/ckaufmann/gpu-cluster-images"
    LABEL org.opencontainers.image.revision=$LABEL_REVISION
    LABEL org.opencontainers.image.vendor="UAS Bochum"
    LABEL org.opencontainers.image.licenses=BSD-3-Clause
    LABEL org.opencontainers.image.title="Jupyter Notebook Keras 3 CPU image"
    LABEL org.opencontainers.image.description="This image includes TensorFlow and Keras 3 without GPU support, VS Code CLI, code-server and nbgitpuller."
    LABEL org.opencontainers.image.base.name=quay.io/jupyter/tensorflow-notebook:latest
    
    # switch back to jovyan to avoid accidental container runs as root
    USER ${NB_UID}
    WORKDIR "${HOME}"
    
    
    ###################################################################
    ######################## Testing the image ########################
    ###################################################################
    FROM build AS test
    
    # replace home directory with skel, which is closer to the kubernetes environment
    USER root
    RUN cd / && \
        rm -r "/home/${NB_USER}" && \
        cp -r /etc/skel "/home/${NB_USER}" && \
        fix-permissions "/home/${NB_USER}"
    USER ${NB_UID}
    
    # enable logging for all Jupyter applications
    RUN printf '%s\n' \
        "" \
        "# Filter out user connection hint message, which is a CRITICAL logger message" \
        "import logging" \
        "class UserHintFilter(logging.Filter):" \
        "    def filter(self, record):" \
        "        return 'To access the server' not in record.getMessage()" \
        "" \
        "c.Application.logging_config = {" \
        "    'filters': {" \
        "        'user_hint': {" \
        "            '()': UserHintFilter," \
        "        }," \
        "    }," \
        "    'formatters': {" \
        "        'file': {" \
        "            'format': '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'," \
        "        }," \
        "    }," \
        "    'handlers': {" \
        "        'file': {" \
        "            'class': 'logging.FileHandler'," \
        "            'filters': ['user_hint']," \
        "            'formatter': 'file'," \
        "            'level': 'INFO'," \
        "            'filename': '/home/jovyan/jupyter.log'," \
        "        }," \
        "    }," \
        "    'loggers': {" \
        "        'Application': {" \
        "            'level': 'DEBUG'," \
        "            'handlers': ['console', 'file']," \
        "        }," \
        "    }," \
        "    'loggers': {" \
        "        'JupyterApp': {" \
        "            'level': 'DEBUG'," \
        "            'handlers': ['console', 'file']," \
        "        }," \
        "    }," \
        "    'loggers': {" \
        "        'ExtensionApp': {" \
        "            'level': 'DEBUG'," \
        "            'handlers': ['console', 'file']," \
        "        }," \
        "    }," \
        "    'loggers': {" \
        "        'LabServerApp': {" \
        "            'level': 'DEBUG'," \
        "            'handlers': ['console', 'file']," \
        "        }," \
        "    }," \
        "    'loggers': {" \
        "        'LabApp': {" \
        "            'level': 'DEBUG'," \
        "            'handlers': ['console', 'file']," \
        "        }," \
        "    }," \
        "    'loggers': {" \
        "        'NotebookApp': {" \
        "            'level': 'DEBUG'," \
        "            'handlers': ['console', 'file']," \
        "        }," \
        "    }," \
        "    'loggers': {" \
        "        'ServerApp': {" \
        "            'level': 'DEBUG'," \
        "            'handlers': ['console', 'file']," \
        "        }," \
        "    }," \
        "}" \
        >> /etc/jupyter/jupyter_notebook_config.py
    
    
    # collect lab logs for 4 sec
    RUN start-notebook.sh & sleep 4 && kill -INT %1 && sleep 1
    
    # check log file:
        # not existing means some error prevents logging → bad
    RUN [[ -f jupyter.log ]] \
        || ( echo "Log file jupyter.log does not exist!" && false ) \
        # existing, contains error → bad, print log file
        && ! grep -qP '(Traceback|ERROR|CRITICAL)' jupyter.log \
        || ( cat jupyter.log && false )
    
    
    # add some environment variables and collect lab logs again for 4 sec
    RUN mv jupyter.log jupyter1.log
    ENV MEM_LIMIT=1000000000 \
        CPU_LIMIT=16.0
    RUN start-notebook.sh & sleep 4 && kill -INT %1 && sleep 1
    
    # check log file:
        # not existing means some error prevents logging → bad
    RUN [[ -f jupyter.log ]] \
        || ( echo "Log file jupyter.log does not exist!" && false ) \
        # existing, contains error → bad, print log file
        && ! grep -qP '(Traceback|ERROR|CRITICAL)' jupyter.log \
        || ( cat jupyter.log && false )