Last active
July 17, 2022 21:42
-
-
Save darkarnium/d56eb29d12dd00a65b83391e42d5604d to your computer and use it in GitHub Desktop.
JupyterLab Helper - Installs, configures, and runs JupyterLab in a container.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# NOTE: This script enables the JupterLab Extension Manager and installs extensions. | |
# There are code-execution risks with this, so make sure you only use trusted | |
# extensions and you're comfortable with these extensions before running! | |
# | |
# This script wrappers the JupterLab Docker container. It defines a few Docker volume | |
# mounts to ensure that JupyterLab configuration and notebooks are persisted between | |
# restarts. | |
# | |
# Additionally, it defines a requirements.txt which is automatically pip installed at | |
# container start to ensure that all dependencies are available between restarts, and | |
# installs JupyterLab extensions at the same time. | |
# | |
# If the lab container version changes, plugins and their associated Python dependencies | |
# may need updating. | |
LAB_CONTAINER="jupyter/base-notebook:lab-3.1.10" | |
function wait_for_jupyterlab { | |
while [ 1 ]; do | |
curl -s -m5 -o /dev/null -f http://127.0.0.1:8888 | |
if [ $? -eq 0 ]; then | |
break | |
fi | |
echo -n "." | |
sleep 1 | |
done | |
} | |
# Ensure the required directory structure exists. | |
mkdir -p "${PWD}/jupyterlab/work" | |
mkdir -p "${PWD}/jupyterlab/configuration" | |
mkdir -p "${PWD}/jupyterlab/start-up" | |
# Create the requirements list, if not present. | |
if [ ! -e "${PWD}/jupyterlab/requirements.txt" ]; then | |
cat > "${PWD}/jupyterlab/requirements.txt" <<EOF | |
requests | |
boto3 | |
jmespath | |
python-lsp-server[all] | |
black | |
isort | |
pandas | |
jupyterlab-lsp==3.8.1 | |
jupyterlab_code_formatter==1.4.10 | |
jupyterlab_widgets==1.1.1 | |
ipycytoscape==1.3.3 | |
networkx==2.8.4 | |
EOF | |
fi | |
# Create the bootstrap script, if not present. | |
if [ ! -e "${PWD}/jupyterlab/start-up/packages.sh" ]; then | |
cat > "${PWD}/jupyterlab/start-up/packages.sh" <<EOF | |
#!/bin/sh | |
pip install -r /home/jovyan/requirements.txt | |
jupyter labextension install @ryantam626/[email protected] | |
jupyter labextension install @krassowski/[email protected] | |
EOF | |
chmod a+x "${PWD}/jupyterlab/start-up/packages.sh" | |
fi | |
# Flag whether a restart is required after start-up. This is used as some extensions | |
# require a full restart of JupterLab before they will function. We set this based on | |
# the installation of configuration, rather than the plugin itself, for simplicity but | |
# at the cost of accuracy if no configuration is added for a given plugin. | |
JL_RECONFIG=0 | |
# Install advanced settings, if not present. | |
CF_SETTINGS="${PWD}/jupyterlab/configuration/lab/user-settings/@ryantam626/jupyterlab_code_formatter/settings.jupyterlab-settings" | |
NE_SETTINGS="${PWD}/jupyterlab/configuration/lab/user-settings/@jupyterlab/notebook-extension/tracker.jupyterlab-settings" | |
EM_SETTINGS="${PWD}/jupyterlab/configuration/lab/user-settings/@jupyterlab/extensionmanager-extension/plugin.jupyterlab-settings" | |
if [ ! -e "${CF_SETTINGS}" ]; then | |
mkdir -p "`dirname ${CF_SETTINGS}`" | |
JL_RECONFIG=1 | |
cat > "${CF_SETTINGS}" <<EOF | |
{ | |
"formatOnSave": true, | |
"preferences": { | |
"default_formatter": { | |
"python": ["isort", "black"] | |
} | |
} | |
} | |
EOF | |
fi | |
if [ ! -e "${NE_SETTINGS}" ]; then | |
mkdir -p "`dirname ${NE_SETTINGS}`" | |
JL_RECONFIG=1 | |
cat > "${NE_SETTINGS}" <<EOF | |
{ | |
"codeCellConfig": { | |
"rulers": [88] | |
} | |
} | |
EOF | |
fi | |
if [ ! -e "${EM_SETTINGS}" ]; then | |
mkdir -p "`dirname ${EM_SETTINGS}`" | |
JL_RECONFIG=1 | |
cat > "${EM_SETTINGS}" <<EOF | |
{ | |
"disclaimed": true | |
} | |
EOF | |
fi | |
# Attempt to start any existing container. | |
docker start JupyterLab > /dev/null 2>&1 | |
# No container? Start one. | |
if [ $? -ne 0 ]; then | |
docker run \ | |
-itd \ | |
--name JupyterLab \ | |
-p 127.0.0.1:8888:8888 \ | |
-e JUPYTER_ENABLE_LAB=yes \ | |
-e RESTARTABLE=yes \ | |
-u root \ | |
-e GRANT_SUDO=yes \ | |
-v"${PWD}/jupyterlab/work":/home/jovyan/work \ | |
-v"${PWD}/jupyterlab/configuration":/home/jovyan/.jupyter \ | |
-v"${PWD}/jupyterlab/requirements.txt":/home/jovyan/requirements.txt \ | |
-v"${PWD}/jupyterlab/start-up":/usr/local/bin/start-notebook.d/ \ | |
-v /var/run/docker.sock:/var/run/docker.sock \ | |
"${LAB_CONTAINER}" | |
fi | |
# Get token and print to STDOUT. | |
echo -n 'INFO: Waiting for JupyterLab to start...' | |
wait_for_jupyterlab | |
echo "DONE" | |
# If the JupterLab configuration has been changed, restart the container to make sure | |
# everything is correct. | |
if [ $JL_RECONFIG -gt 0 ]; then | |
echo -n 'INFO: JupterLab restarting due to configuration change...' | |
docker restart JupyterLab > /dev/null 2>&1 | |
wait_for_jupyterlab | |
fi | |
echo "DONE" | |
# Grab the JupyterLab token / URL. | |
echo -n 'INFO: Fetching JupyterLab token from logs...' | |
JUPYTER_URL=$(docker logs JupyterLab | grep -Eio 'http.*?token=[0-9a-f]+' | tail -n 1) | |
echo "DONE" | |
# Finally good to go! | |
echo "INFO: JupyterLab available at ${JUPYTER_URL}" | |
echo 'INFO: Attempting to open JupyterLab in browser...' | |
if [ -n "$(which open)" ]; then | |
open "${JUPYTER_URL}" | |
else | |
echo "INFO: No 'open' on this system, not opening browser." | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment