From 264d6faa9460a784d6bff58498bf7181092dd42c Mon Sep 17 00:00:00 2001 From: Julien Chastang Date: Wed, 22 Jan 2025 11:32:08 -0700 Subject: [PATCH] fit25s --- .../spring-2025/fit/Acknowledgements.ipynb | 43 ++++++++++++ jupyter-images/spring-2025/fit/Dockerfile | 51 ++++++++++++++ jupyter-images/spring-2025/fit/build.sh | 44 +++++++++++++ .../fit/environment-fit25s-era5.yml | 33 ++++++++++ .../fit/environment-fit25s-sounder.yml | 33 ++++++++++ jupyter-images/spring-2025/fit/overrides.json | 7 ++ jupyter-images/spring-2025/fit/secrets.yaml | 66 +++++++++++++++++++ 7 files changed, 277 insertions(+) create mode 100644 jupyter-images/spring-2025/fit/Acknowledgements.ipynb create mode 100644 jupyter-images/spring-2025/fit/Dockerfile create mode 100755 jupyter-images/spring-2025/fit/build.sh create mode 100644 jupyter-images/spring-2025/fit/environment-fit25s-era5.yml create mode 100644 jupyter-images/spring-2025/fit/environment-fit25s-sounder.yml create mode 100644 jupyter-images/spring-2025/fit/overrides.json create mode 100644 jupyter-images/spring-2025/fit/secrets.yaml diff --git a/jupyter-images/spring-2025/fit/Acknowledgements.ipynb b/jupyter-images/spring-2025/fit/Acknowledgements.ipynb new file mode 100644 index 00000000..fae591fc --- /dev/null +++ b/jupyter-images/spring-2025/fit/Acknowledgements.ipynb @@ -0,0 +1,43 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c86cd54f-b73c-4781-b6eb-89c79d3d3b22", + "metadata": {}, + "source": [ + "## Acknowledgements\n", + "\n", + "Launching this JupyterHub server is the result of a collaboration between several research and academic institutions and their staff. For Jetstream2 and JupyterHub expertise, we thank Andrea Zonca (San Diego Supercomputing Center), Jeremy Fischer, Mike Lowe (Indiana University), the NSF Jetstream2 (`doi:10.1145/3437359.3465565`) team.\n", + "\n", + "This work employs the NSF Jetstream2 Cloud at Indiana University through allocation EES220002 from the Advanced Cyberinfrastructure Coordination Ecosystem: Services & Support (ACCESS) program, which is supported by National Science Foundation grants #2138259, #2138286, #2138307, #2137603, and #2138296.\n", + "\n", + "Unidata is one of the University Corporation for Atmospheric Research (UCAR)'s Community Programs (UCP), and is funded primarily by the National Science Foundation (AGS-2403649).\n", + "\n", + "## To Acknowledge This JupyterHub and the Unidata Science Gateway\n", + "\n", + "If you have benefited from the Unidata Science Gateway, please cite `doi:10.5065/688s-2w73`. Additional citation information can be found in this [Citation File Format file](https://raw.githubusercontent.com/Unidata/science-gateway/master/CITATION.cff).\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/jupyter-images/spring-2025/fit/Dockerfile b/jupyter-images/spring-2025/fit/Dockerfile new file mode 100644 index 00000000..68e2005c --- /dev/null +++ b/jupyter-images/spring-2025/fit/Dockerfile @@ -0,0 +1,51 @@ +# Heavily borrowed from docker-stacks/minimal-notebook/ +# https://github.com/jupyter/docker-stacks/blob/main/minimal-notebook/Dockerfile + +ARG BASE_CONTAINER=quay.io/jupyter/minimal-notebook +FROM $BASE_CONTAINER + +ENV EDITOR=nano VISUAL=nano + +LABEL maintainer="Unidata " + +USER root + +RUN apt-get update && \ + apt-get install -y --no-install-recommends vim nano curl zip unzip && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +USER $NB_UID + +# Add environment files +ADD environment-fit25s-sounder.yml /tmp/ +ADD environment-fit25s-era5.yml /tmp/ + +# Define and create conda environments +ARG ENVIRONMENTS="fit25s-sounder fit25s-era5" + +RUN for env in $ENVIRONMENTS; do \ + mamba create --name $env --quiet --yes && \ + mamba install --quiet --yes \ + 'conda-forge::nodejs' \ + 'conda-forge::nb_conda_kernels' \ + 'conda-forge::ipykernel' \ + 'conda-forge::jupyterlab-git' \ + 'conda-forge::ipywidgets' && \ + mamba env update --name $env -f /tmp/environment-$env.yml && \ + pip install --no-cache-dir nbgitpuller; \ + done && \ + mamba clean --all -f -y && \ + fix-permissions $CONDA_DIR && \ + jupyter lab clean -y && \ + npm cache clean --force && \ + rm -rf /home/$NB_USER/.cache/yarn && \ + rm -rf /home/$NB_USER/.node-gyp && \ + fix-permissions /home/$NB_USER + +COPY Acknowledgements.ipynb / + +ARG JUPYTER_SETTINGS_DIR=/opt/conda/share/jupyter/lab/settings/ +COPY overrides.json $JUPYTER_SETTINGS_DIR + +USER $NB_UID diff --git a/jupyter-images/spring-2025/fit/build.sh b/jupyter-images/spring-2025/fit/build.sh new file mode 100755 index 00000000..a3abfb74 --- /dev/null +++ b/jupyter-images/spring-2025/fit/build.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status +set -e + +usage() { + echo "Usage: $0 [--push]" + echo " Name of the Docker image to build" + echo " --push Optionally push the Docker image to DockerHub" + exit 1 +} + +if [ -z "$1" ]; then + echo "Error: No image name provided." + usage +fi + +IMAGE_NAME=$1 +PUSH_IMAGE=false + +if [ "$2" == "--push" ]; then + PUSH_IMAGE=true +fi + +DATE_TAG=$(date "+%Y%b%d_%H%M%S") +RANDOM_HEX=$(openssl rand -hex 2) +TAG="${DATE_TAG}_${RANDOM_HEX}" +FULL_TAG="unidata/$IMAGE_NAME:$TAG" + +# Build the Docker image +echo "Building Docker image with tag: $FULL_TAG" +docker build --no-cache --pull --tag "$FULL_TAG" . + +echo "Docker image built successfully: $FULL_TAG" + +if $PUSH_IMAGE; then + echo "Pushing Docker image to DockerHub: $FULL_TAG" + docker push "$FULL_TAG" + echo "Docker image pushed successfully: $FULL_TAG" +else + echo "Skipping Docker image push. Use '--push' to push the image." +fi + +exit 0 diff --git a/jupyter-images/spring-2025/fit/environment-fit25s-era5.yml b/jupyter-images/spring-2025/fit/environment-fit25s-era5.yml new file mode 100644 index 00000000..644cd5f9 --- /dev/null +++ b/jupyter-images/spring-2025/fit/environment-fit25s-era5.yml @@ -0,0 +1,33 @@ +name: fit25s-era5 +channels: + - conda-forge +dependencies: + # Required by JupyterLab + - 'python<3.13' + - nb_conda_kernels + - ipykernel + # User requested packages + - arm_pyart + - boto3 + - botocore + - cartopy + - cf_xarray + - era5cli + - geopandas + - ipywidgets + - keras + - matplotlib + - metpy + - netCDF4 + - numpy + - pandas + - pint + - pip + - python-awips + - scikit-learn + - scipy + - seaborn + - siphon + - tensorflow + - xarray + - xesmf diff --git a/jupyter-images/spring-2025/fit/environment-fit25s-sounder.yml b/jupyter-images/spring-2025/fit/environment-fit25s-sounder.yml new file mode 100644 index 00000000..4006577b --- /dev/null +++ b/jupyter-images/spring-2025/fit/environment-fit25s-sounder.yml @@ -0,0 +1,33 @@ +name: fit25s-sounder +channels: + - conda-forge +dependencies: + # Required by JupyterLab + - 'python<3.13' + - nb_conda_kernels + - ipykernel + # User requested packages + - arm_pyart + - boto3 + - botocore + - cartopy + - cf_xarray + - geopandas + - ipywidgets + - keras + - matplotlib + - metpy + - netCDF4 + - numpy + - pandas + - pint + - pip + - python-awips + - scikit-learn + - scipy + - seaborn + - siphon + - sounderpy + - tensorflow + - xarray + - xesmf diff --git a/jupyter-images/spring-2025/fit/overrides.json b/jupyter-images/spring-2025/fit/overrides.json new file mode 100644 index 00000000..c60d6b61 --- /dev/null +++ b/jupyter-images/spring-2025/fit/overrides.json @@ -0,0 +1,7 @@ +{ + "@jupyterlab/docmanager-extension:plugin": { + "defaultViewers": { + "markdown": "Markdown Preview" + } + } +} diff --git a/jupyter-images/spring-2025/fit/secrets.yaml b/jupyter-images/spring-2025/fit/secrets.yaml new file mode 100644 index 00000000..ea9b49eb --- /dev/null +++ b/jupyter-images/spring-2025/fit/secrets.yaml @@ -0,0 +1,66 @@ +hub: + cookieSecret: "xxx" + config: + Authenticator: + admin_users: + - admins + #If you have a large list of users, consider using allowed_users.yaml + allowed_users: + - users + # necessary for jhub admins to add user via admin page `/hub/admin` + allow_existing_users: true + GitHubOAuthenticator: + client_id: "xxx" + client_secret: "xxx" + oauth_callback_url: "https://fit25s-1.ees220002.projects.jetstream-cloud.org:443/oauth_callback" + JupyterHub: + authenticator_class: github + + +proxy: + secretToken: "xxx" + +ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + cert-manager.io/cluster-issuer: "letsencrypt" + #For manually issuing certificates: see vms/jupyter/readme.md + #cert-manager.io/issuer: "incommon" + nginx.ingress.kubernetes.io/proxy-body-size: 500m + hosts: + - "fit25s-1.ees220002.projects.jetstream-cloud.org" + tls: + - hosts: + - "fit25s-1.ees220002.projects.jetstream-cloud.org" + secretName: certmanager-tls-jupyterhub + +singleuser: + extraEnv: + NBGITPULLER_DEPTH: "0" + storage: + capacity: 10Gi + startTimeout: 600 + memory: + guarantee: 4G + limit: 4G + cpu: + guarantee: 1 + limit: 2 + defaultUrl: "/lab" + image: + name: "unidata/" + tag: "xxx" + lifecycleHooks: + postStart: + exec: + command: + - "bash" + - "-c" + - > + dir="/home/jovyan/.ssh"; [ -d $dir ] && { chmod 700 $dir && chmod -f 600 $dir/* && chmod -f 644 $dir/*.pub; } || true; + cp -t /home/jovyan /Acknowledgements.ipynb; + [[ -f $HOME/.bashrc ]] || cp /etc/skel/.bashrc $HOME/; + [[ -f $HOME/.profile ]] || cp /etc/skel/.profile $HOME/; + [[ -f $HOME/.bash_logout ]] || cp /etc/skel/.bash_logout $HOME/; + [ -d "/share" ] && [ ! -L ~/share ] && ln -s /share ~/share || true;