From 1dbf2ee64085da60ecf09d8017809d72e55ce601 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Sat, 5 Mar 2022 00:46:56 +0000 Subject: [PATCH 01/11] Add JupyterLab as a feature If Python is not installed, error out and tell the user that it's missing. --- .../src/devcontainer-features.json | 18 ++++++ script-library/docs/jupyterlab.md | 57 +++++++++++++++++++ script-library/jupyterlab-debian.sh | 28 +++++++++ 3 files changed, 103 insertions(+) create mode 100644 script-library/docs/jupyterlab.md create mode 100644 script-library/jupyterlab-debian.sh diff --git a/script-library/container-features/src/devcontainer-features.json b/script-library/container-features/src/devcontainer-features.json index 76f6382c48..4dfe3c2557 100644 --- a/script-library/container-features/src/devcontainer-features.json +++ b/script-library/container-features/src/devcontainer-features.json @@ -1121,6 +1121,24 @@ "ruby-rails-postgres", "python-3-postgres" ] + }, + { + "id": "jupyterlab", + "name": "Jupyter Lab", + "documentationURL": "https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/jupyterlab.md", + "options": { + "version": { + "type": "string", + "proposals": ["latest", "3.6.2"], + "default": "latest", + "description": "Select or enter a jupyterlab version." + } + }, + "buildArg": "_VSC_INSTALL_JUPYTERLAB", + "extensions": [], + "include": [ + "codespaces-linux" + ] } ] } diff --git a/script-library/docs/jupyterlab.md b/script-library/docs/jupyterlab.md new file mode 100644 index 0000000000..d6639de216 --- /dev/null +++ b/script-library/docs/jupyterlab.md @@ -0,0 +1,57 @@ +# JupyterLab Install Script + +*Installs JupyterLab.* + +**Script status**: Stable + +**OS support**: Debian 9+, Ubuntu 18.04+, and downstream distros. + +**Maintainer**: GitHub Codespaces team + +## Syntax + +```text +./jupyterlab-debian.sh +``` + +Or as a feature: + +```json +"features": { + "jupyterlab": { + "version": "latest" + } +} +``` + +## Usage + +### Feature use + +To install this feature in your primary dev container, reference it in `devcontainer.json` as follows: + +```json +"features": { + "jupyterlab": { + "version": "latest" + } +} +``` + +If you have already built your development container, run the **Rebuild Container** command from the command +palette (Ctrl/Cmd + Shift + P or F1) to pick up the change. + +You must have Python already installed in order to use this feature. + +### Script use + +1. Add [`jupyterlab-debian.sh`](../jupyterlab-debian.sh) to `.devcontainer/library-scripts` + +2. Add the following to your `.devcontainer/Dockerfile`: + + ```Dockerfile + COPY library-scripts/jupyterlab-debian.sh /tmp/library-scripts/ + RUN bash /tmp/library-scripts/jupyterlab-debian.sh + ``` + +That's it! diff --git a/script-library/jupyterlab-debian.sh b/script-library/jupyterlab-debian.sh new file mode 100644 index 0000000000..1b61509884 --- /dev/null +++ b/script-library/jupyterlab-debian.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/jupyterlab.md +# Maintainer: The VS Code and Codespaces Teams +# +# Syntax: ./jupyter-debian.sh + +set -e + +JUPYTER_LAB_VERSION=${1:-"latest"} + +# If we don't yet have Python, install it now. +if ! python --version > /dev/null ; then + echo "You need to install Python before installing JupyterLab." + exit 1 +fi + +# Install JupyterLab +echo "Installing JupyterLab..." +if [ "${JUPYTER_LAB_VERSION}" = "latest" ]; then + pip install jupyterlab +else + pip install jupyterlab=="${JUPYTER_LAB_VERSION}" +fi From 7e0cc82d3fac898198955189c8a3fe1da537530c Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Tue, 8 Mar 2022 11:33:44 -0600 Subject: [PATCH 02/11] Use --no-cache-dir when installing jupyterlab with pip. --- script-library/jupyterlab-debian.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script-library/jupyterlab-debian.sh b/script-library/jupyterlab-debian.sh index 1b61509884..2474070592 100644 --- a/script-library/jupyterlab-debian.sh +++ b/script-library/jupyterlab-debian.sh @@ -24,5 +24,5 @@ echo "Installing JupyterLab..." if [ "${JUPYTER_LAB_VERSION}" = "latest" ]; then pip install jupyterlab else - pip install jupyterlab=="${JUPYTER_LAB_VERSION}" + pip install jupyterlab=="${JUPYTER_LAB_VERSION}" --no-cache-dir fi From bc9979c4bc878fdc975355f519bdb84b794e7fb4 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Wed, 9 Mar 2022 14:01:06 -0600 Subject: [PATCH 03/11] Updates to JupyterLab feature. --- .../src/devcontainer-features.json | 12 ++++++++++-- .../container-features/src/feature-scripts.env | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/script-library/container-features/src/devcontainer-features.json b/script-library/container-features/src/devcontainer-features.json index 4dfe3c2557..c78064c3c9 100644 --- a/script-library/container-features/src/devcontainer-features.json +++ b/script-library/container-features/src/devcontainer-features.json @@ -1135,9 +1135,17 @@ } }, "buildArg": "_VSC_INSTALL_JUPYTERLAB", - "extensions": [], + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ], "include": [ - "codespaces-linux" + "codespaces-linux", + "python-3", + "python-3-anaconda", + "python-3-miniconda", + "ubuntu", + "debian" ] } ] diff --git a/script-library/container-features/src/feature-scripts.env b/script-library/container-features/src/feature-scripts.env index 90136fcd1e..1c2216d721 100644 --- a/script-library/container-features/src/feature-scripts.env +++ b/script-library/container-features/src/feature-scripts.env @@ -20,3 +20,4 @@ _VSC_INSTALL_RUST="rust-debian.sh /usr/local/cargo /usr/local/rustup automatic t _VSC_INSTALL_POWERSHELL="powershell-debian.sh ${_BUILD_ARG_POWERSHELL_VERSION:-latest}" _VSC_INSTALL_DESKTOP_LITE="desktop-lite-debian.sh automatic ${_BUILD_ARG_DESKTOP_LITE_PASSWORD:-vscode} true ${_BUILD_ARG_DESKTOP_LITE_VNCPORT:-5901} ${_BUILD_ARG_DESKTOP_LITE_WEBPORT:-6080}" _VSC_INSTALL_DOTNET="dotnet-debian.sh ${_BUILD_ARG_DOTNET_VERSION:-latest} ${_BUILD_ARG_DOTNET_RUNTIMEONLY:-false} automatic true /usr/local/dotnet dotnet" +_VSC_INSTALL_JUPYTERLAB="jupyterlab-debian.sh ${_BUILD_ARG_JUPYTERLAB_VERSION:-latest}" From fbca535699615fd2949f2e7c0da8f37d2fb3ebd3 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Wed, 9 Mar 2022 14:06:22 -0600 Subject: [PATCH 04/11] Rename JUPYTER_LAB_VERSION to just VERSION. --- script-library/jupyterlab-debian.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/script-library/jupyterlab-debian.sh b/script-library/jupyterlab-debian.sh index 2474070592..87eb77359d 100644 --- a/script-library/jupyterlab-debian.sh +++ b/script-library/jupyterlab-debian.sh @@ -11,7 +11,7 @@ set -e -JUPYTER_LAB_VERSION=${1:-"latest"} +VERSION=${1:-"latest"} # If we don't yet have Python, install it now. if ! python --version > /dev/null ; then @@ -21,8 +21,8 @@ fi # Install JupyterLab echo "Installing JupyterLab..." -if [ "${JUPYTER_LAB_VERSION}" = "latest" ]; then +if [ "${VERSION}" = "latest" ]; then pip install jupyterlab else - pip install jupyterlab=="${JUPYTER_LAB_VERSION}" --no-cache-dir + pip install jupyterlab=="${VERSION}" --no-cache-dir fi From 5a67aecbf59604e4a3003a0f676560033a5aa716 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Wed, 9 Mar 2022 14:51:46 -0600 Subject: [PATCH 05/11] Only install JupyterLab if it's not yet installed. --- script-library/jupyterlab-debian.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/script-library/jupyterlab-debian.sh b/script-library/jupyterlab-debian.sh index 87eb77359d..406baf8ad6 100644 --- a/script-library/jupyterlab-debian.sh +++ b/script-library/jupyterlab-debian.sh @@ -19,10 +19,12 @@ if ! python --version > /dev/null ; then exit 1 fi -# Install JupyterLab -echo "Installing JupyterLab..." -if [ "${VERSION}" = "latest" ]; then - pip install jupyterlab -else - pip install jupyterlab=="${VERSION}" --no-cache-dir +# If we don't already have JupyterLab installed, install it now. +if ! jupyter-lab --version > /dev/null ; then + echo "Installing JupyterLab..." + if [ "${VERSION}" = "latest" ]; then + pip install jupyterlab + else + pip install jupyterlab=="${VERSION}" --no-cache-dir + fi fi From 4e2aabc93b6b3d56b4caf539a22ea757f13a206f Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Thu, 10 Mar 2022 10:41:18 -0600 Subject: [PATCH 06/11] Update README --- script-library/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/script-library/README.md b/script-library/README.md index 359d30c4a5..7fd2b66837 100644 --- a/script-library/README.md +++ b/script-library/README.md @@ -28,6 +28,7 @@ Some scripts have special installation instructions (like `desktop-lite-debian.s | [Gradle Install Script](docs/gradle.md) | `gradle-debian.sh` | VS Code and GitHub Codespaces teams| | [Homebrew Install Script](docs/homebrew.md) | `homebrew-debian.sh` (Community) | [@andreiborisov](https://github.com/andreiborisov) | | [Java Install Script](docs/java.md) | `java-debian.sh` | VS Code and GitHub Codespaces teams| +| [JupyterLab Install Script](docs/jupyterlab.md) | `jupyterlab-debian.sh` | VS Code and GitHub Codespaces teams| | [Kubectl and Helm Install Script](docs/kubectl-helm.md) | `kubectl-helm-debian.sh` | VS Code and GitHub Codespaces teams| | [Maven Install Script](docs/maven.md) | `maven-debian.sh` | VS Code and GitHub Codespaces teams| | [Node.js Install Script](docs/node.md) | `node-debian.sh` | VS Code and GitHub Codespaces teams| From 5969fd2c4f7f5231994402f3ed5ff0e1f179f2cb Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Thu, 10 Mar 2022 10:57:47 -0600 Subject: [PATCH 07/11] Add ms-toolsai.jupyter extension. --- .../container-features/src/devcontainer-features.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script-library/container-features/src/devcontainer-features.json b/script-library/container-features/src/devcontainer-features.json index c78064c3c9..0e1a2868cf 100644 --- a/script-library/container-features/src/devcontainer-features.json +++ b/script-library/container-features/src/devcontainer-features.json @@ -1137,7 +1137,8 @@ "buildArg": "_VSC_INSTALL_JUPYTERLAB", "extensions": [ "ms-python.python", - "ms-python.vscode-pylance" + "ms-python.vscode-pylance", + "ms-toolsai.jupyter" ], "include": [ "codespaces-linux", From 3db544ed8f75eac2e0dcf77c519c2afabad95334 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Thu, 10 Mar 2022 12:33:36 -0600 Subject: [PATCH 08/11] [python-3-anaconda] Copy all library scripts. --- containers/python-3-anaconda/.devcontainer/base.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/containers/python-3-anaconda/.devcontainer/base.Dockerfile b/containers/python-3-anaconda/.devcontainer/base.Dockerfile index 54576c038e..6b911c24fb 100644 --- a/containers/python-3-anaconda/.devcontainer/base.Dockerfile +++ b/containers/python-3-anaconda/.devcontainer/base.Dockerfile @@ -14,7 +14,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/base:0-bullseye COPY --from=upstream /opt /opt/ # Copy library scripts to execute -COPY .devcontainer/library-scripts/node-debian.sh .devcontainer/add-notice.sh .devcontainer/library-scripts/*.env /tmp/library-scripts/ +COPY .devcontainer/library-scripts/*.sh .devcontainer/add-notice.sh .devcontainer/library-scripts/*.env /tmp/library-scripts/ # Setup conda to mirror contents from https://github.com/ContinuumIO/docker-images/blob/master/anaconda3/debian/Dockerfile ENV LANG=C.UTF-8 \ From 88edc5678a25a85c9f65d85131e97fa719dae544 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Thu, 10 Mar 2022 16:20:02 -0600 Subject: [PATCH 09/11] Install JupyterLab as non-root user. --- script-library/jupyterlab-debian.sh | 34 +++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) mode change 100644 => 100755 script-library/jupyterlab-debian.sh diff --git a/script-library/jupyterlab-debian.sh b/script-library/jupyterlab-debian.sh old mode 100644 new mode 100755 index 406baf8ad6..fab8bc957e --- a/script-library/jupyterlab-debian.sh +++ b/script-library/jupyterlab-debian.sh @@ -12,6 +12,36 @@ set -e VERSION=${1:-"latest"} +USERNAME=${2:-"automatic"} + +# If in automatic mode, determine if a user already exists, if not use vscode +if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then + USERNAME="" + POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") + for CURRENT_USER in ${POSSIBLE_USERS[@]}; do + if id -u ${CURRENT_USER} > /dev/null 2>&1; then + USERNAME=${CURRENT_USER} + break + fi + done + if [ "${USERNAME}" = "" ]; then + USERNAME=vscode + fi +elif [ "${USERNAME}" = "none" ]; then + USERNAME=root + USER_UID=0 + USER_GID=0 +fi + +# Use sudo to run as non-root user is not already running +sudoUserIf() +{ + if [ "$(id -u)" -eq 0 ] && [ "${USERNAME}" != "root" ]; then + sudo -u ${USERNAME} "$@" + else + "$@" + fi +} # If we don't yet have Python, install it now. if ! python --version > /dev/null ; then @@ -23,8 +53,8 @@ fi if ! jupyter-lab --version > /dev/null ; then echo "Installing JupyterLab..." if [ "${VERSION}" = "latest" ]; then - pip install jupyterlab + sudoUserIf pip install jupyterlab else - pip install jupyterlab=="${VERSION}" --no-cache-dir + sudoUserIf pip install jupyterlab=="${VERSION}" --no-cache-dir fi fi From 3078ef2d16124e03e125e62c1854b59bf08a5570 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Thu, 10 Mar 2022 17:32:11 -0600 Subject: [PATCH 10/11] [codespaces] Don't install JupyterLab with pip, use the feature instead. --- .../.devcontainer/base.Dockerfile | 2 +- .../library-scripts/jupyterlab-debian.sh | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100755 containers/codespaces-linux/.devcontainer/library-scripts/jupyterlab-debian.sh diff --git a/containers/codespaces-linux/.devcontainer/base.Dockerfile b/containers/codespaces-linux/.devcontainer/base.Dockerfile index b3faf59580..9fef56372a 100644 --- a/containers/codespaces-linux/.devcontainer/base.Dockerfile +++ b/containers/codespaces-linux/.devcontainer/base.Dockerfile @@ -72,12 +72,12 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ # Install Python, PHP, Ruby utilities, and JupyterLab RUN bash /tmp/scripts/python-debian.sh "none" "/opt/python/latest" "${PIPX_HOME}" "${USERNAME}" "true" \ + && bash /tmp/scripts/jupyterlab-debian.sh \ # Install rvm, rbenv, any missing base gems && chown -R ${USERNAME} /opt/ruby/* \ && bash /tmp/scripts/ruby-debian.sh "none" "${USERNAME}" "true" "true" \ # Link composer && ln -s $(which composer.phar) /usr/local/bin/composer \ - && pip install jupyterlab \ && apt-get clean -y # Install PowerShell diff --git a/containers/codespaces-linux/.devcontainer/library-scripts/jupyterlab-debian.sh b/containers/codespaces-linux/.devcontainer/library-scripts/jupyterlab-debian.sh new file mode 100755 index 0000000000..fab8bc957e --- /dev/null +++ b/containers/codespaces-linux/.devcontainer/library-scripts/jupyterlab-debian.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/jupyterlab.md +# Maintainer: The VS Code and Codespaces Teams +# +# Syntax: ./jupyter-debian.sh + +set -e + +VERSION=${1:-"latest"} +USERNAME=${2:-"automatic"} + +# If in automatic mode, determine if a user already exists, if not use vscode +if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then + USERNAME="" + POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") + for CURRENT_USER in ${POSSIBLE_USERS[@]}; do + if id -u ${CURRENT_USER} > /dev/null 2>&1; then + USERNAME=${CURRENT_USER} + break + fi + done + if [ "${USERNAME}" = "" ]; then + USERNAME=vscode + fi +elif [ "${USERNAME}" = "none" ]; then + USERNAME=root + USER_UID=0 + USER_GID=0 +fi + +# Use sudo to run as non-root user is not already running +sudoUserIf() +{ + if [ "$(id -u)" -eq 0 ] && [ "${USERNAME}" != "root" ]; then + sudo -u ${USERNAME} "$@" + else + "$@" + fi +} + +# If we don't yet have Python, install it now. +if ! python --version > /dev/null ; then + echo "You need to install Python before installing JupyterLab." + exit 1 +fi + +# If we don't already have JupyterLab installed, install it now. +if ! jupyter-lab --version > /dev/null ; then + echo "Installing JupyterLab..." + if [ "${VERSION}" = "latest" ]; then + sudoUserIf pip install jupyterlab + else + sudoUserIf pip install jupyterlab=="${VERSION}" --no-cache-dir + fi +fi From 72931d0ebd3a70499c8467549d9b36ed13578e6f Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Fri, 11 Mar 2022 18:35:16 -0600 Subject: [PATCH 11/11] Add .local/bin to PATH so smoke test will find jupyter-lab. --- containers/codespaces-linux/.devcontainer/base.Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/containers/codespaces-linux/.devcontainer/base.Dockerfile b/containers/codespaces-linux/.devcontainer/base.Dockerfile index 9fef56372a..f3e50f2ec4 100644 --- a/containers/codespaces-linux/.devcontainer/base.Dockerfile +++ b/containers/codespaces-linux/.devcontainer/base.Dockerfile @@ -33,9 +33,10 @@ ENV SHELL=/bin/bash \ CARGO_HOME="/usr/local/cargo" \ RUSTUP_HOME="/usr/local/rustup" \ SDKMAN_DIR="/usr/local/sdkman" \ + JUPYTERLAB_PATH="${HOMEDIR}/.local/bin" \ DOCKER_BUILDKIT=1 -ENV PATH="${NVM_DIR}/current/bin:${NPM_GLOBAL}/bin:${ORIGINAL_PATH}:${DOTNET_ROOT}:${DOTNET_ROOT}/tools:${SDKMAN_DIR}/bin:${SDKMAN_DIR}/candidates/gradle/current/bin:${SDKMAN_DIR}/candidates/java/current/bin:/opt/maven/lts:${CARGO_HOME}/bin:${GOROOT}/bin:${GOPATH}/bin:${PIPX_BIN_DIR}:/opt/conda/condabin:${JAVA_ROOT}/current/bin:${NODE_ROOT}/current/bin:${PHP_ROOT}/current/bin:${PYTHON_ROOT}/current/bin:${RUBY_ROOT}/current/bin:${MAVEN_ROOT}/current/bin:${HUGO_ROOT}/current/bin:${ORYX_PATHS}" +ENV PATH="${NVM_DIR}/current/bin:${NPM_GLOBAL}/bin:${ORIGINAL_PATH}:${DOTNET_ROOT}:${DOTNET_ROOT}/tools:${SDKMAN_DIR}/bin:${SDKMAN_DIR}/candidates/gradle/current/bin:${SDKMAN_DIR}/candidates/java/current/bin:/opt/maven/lts:${CARGO_HOME}/bin:${GOROOT}/bin:${GOPATH}/bin:${PIPX_BIN_DIR}:/opt/conda/condabin:${JAVA_ROOT}/current/bin:${NODE_ROOT}/current/bin:${PHP_ROOT}/current/bin:${PYTHON_ROOT}/current/bin:${RUBY_ROOT}/current/bin:${MAVEN_ROOT}/current/bin:${HUGO_ROOT}/current/bin:${JUPYTERLAB_PATH}:${ORYX_PATHS}" # Install needed utilities and setup non-root user. Use a separate RUN statement to add your own dependencies. COPY library-scripts/* setup-user.sh first-run-notice.txt /tmp/scripts/