Files
OBIJupyterHub/Readme.md

343 lines
8.8 KiB
Markdown
Raw Normal View History

2025-10-15 07:10:44 +02:00
# JupyterHub Configuration with OrbStack on Mac (all in Docker)
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
## Prerequisites
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
You must have docker running on your computer
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
- On MacOS, [OrbStack](https://orbstack.dev/ "A Docker implementation optimised for MacOS") is recommanded
##
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
## Installation Steps
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
### 1. Create Directory Structure
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
``` bash
git clone https://forge.metabarcoding.org/MetabarcodingSchool/OBIJupyterHub.git
2025-10-14 17:40:41 +02:00
```
2025-10-15 15:04:00 +02:00
#### File Structure
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
Your `~/OBIJupyterHub` directory should contain:
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
```
~/OBIJupyterHub/
├── Dockerfile # Image for students (already created)
├── Dockerfile.hub # Image for JupyterHub (new)
├── jupyterhub_config.py # Configuration
├── docker-compose.yml # Orchestration
└── start-jupyterhub.sh # Startup script
2025-10-14 17:40:41 +02:00
```
2025-10-15 15:04:00 +02:00
### 2. Start JupyterHub
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
``` bash
2025-10-15 07:10:44 +02:00
./start-jupyterhub.sh
2025-10-14 17:40:41 +02:00
```
2025-10-15 15:04:00 +02:00
### 3. Access JupyterHub
2025-10-14 17:40:41 +02:00
2025-10-15 14:08:52 +02:00
Open your browser and go to: **http://localhost:8888**
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
You can log in with any username and password: `metabar2025`
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
## Useful Commands
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
### View JupyterHub logs
2025-10-15 15:04:00 +02:00
``` bash
2025-10-14 17:40:41 +02:00
docker-compose logs -f jupyterhub
```
2025-10-15 07:10:44 +02:00
### View all containers (hub + students)
2025-10-15 15:04:00 +02:00
``` bash
docker ps | grep jupyterhub
2025-10-14 17:40:41 +02:00
```
2025-10-15 07:10:44 +02:00
### Stop JupyterHub
2025-10-15 15:04:00 +02:00
``` bash
2025-10-14 17:40:41 +02:00
docker-compose down
```
2025-10-15 07:10:44 +02:00
### Restart JupyterHub (after config modification)
2025-10-15 15:04:00 +02:00
``` bash
2025-10-14 17:40:41 +02:00
docker-compose restart jupyterhub
```
2025-10-15 07:10:44 +02:00
### Rebuild after Dockerfile modification
2025-10-15 15:04:00 +02:00
``` bash
2025-10-15 07:10:44 +02:00
# For student image
2025-10-14 17:40:41 +02:00
docker build -t jupyterhub-student:latest -f Dockerfile .
docker-compose restart jupyterhub
2025-10-15 07:10:44 +02:00
# For hub image
2025-10-14 17:40:41 +02:00
docker-compose up -d --build
```
2025-10-15 07:10:44 +02:00
### View logs for a specific student
2025-10-15 15:04:00 +02:00
``` bash
docker logs jupyter-<username>
2025-10-14 17:40:41 +02:00
```
2025-10-15 15:04:00 +02:00
Replace `<username>` by the actual user name of the student.
2025-10-15 07:10:44 +02:00
### Clean up after lab
2025-10-15 15:04:00 +02:00
``` bash
2025-10-15 07:10:44 +02:00
# Stop and remove all containers
2025-10-14 17:40:41 +02:00
docker-compose down
2025-10-15 07:10:44 +02:00
# Remove student containers
2025-10-14 17:40:41 +02:00
docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f
2025-10-15 07:10:44 +02:00
# Remove volumes (WARNING: deletes student data)
2025-10-14 17:40:41 +02:00
docker volume ls | grep jupyterhub-user | awk '{print $2}' | xargs docker volume rm
2025-10-15 07:10:44 +02:00
# Clean everything (containers + volumes + network)
2025-10-14 17:40:41 +02:00
docker-compose down -v
docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f
docker volume prune -f
```
2025-10-15 07:10:44 +02:00
## Managing Shared Data
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
### Directory Structure for Each Student
2025-10-14 17:40:41 +02:00
2025-10-15 14:08:52 +02:00
Each student will see this directory structure in their JupyterLab (everything under `work/` is persistent):
2025-10-15 15:04:00 +02:00
```
2025-10-15 14:08:52 +02:00
work/ # Personal workspace root (persistent)
├── [student files] # Their own files and notebooks
├── R_packages/ # Personal R packages (writable by student)
├── shared/ # Shared workspace (read/write, shared with all)
└── course/ # Course files (read-only, managed by admin)
├── R_packages/ # Shared R packages (read-only, installed by prof)
├── bin/ # Shared executables (in PATH)
└── [course materials] # Your course files
```
2025-10-15 15:04:00 +02:00
**R Package Priority:** 1. R checks `work/R_packages/` first (personal, writable) 2. Then `work/course/R_packages/` (shared, read-only, installed by prof) 3. Then system libraries
2025-10-15 14:08:52 +02:00
**Important:** Everything is under `work/`, so all student files are automatically saved in their persistent volume.
2025-10-15 07:15:05 +02:00
### User Accounts
2025-10-15 15:04:00 +02:00
**Admin Account:** - Username: `admin` - Password: `admin2025` (change in docker-compose.yml: `JUPYTERHUB_ADMIN_PASSWORD`) - Can write to `course/` directory
2025-10-15 07:15:05 +02:00
2025-10-15 15:04:00 +02:00
**Student Accounts:** - Username: any name - Password: `metabar2025` (change in docker-compose.yml: `JUPYTERHUB_PASSWORD`) - Read-only access to `course/` directory
2025-10-15 07:15:05 +02:00
### Installing R Packages (Admin Only)
**From your Mac (recommended):**
2025-10-15 15:04:00 +02:00
``` bash
2025-10-15 07:15:05 +02:00
chmod +x install-r-packages-admin.sh
# Install packages
./install-r-packages-admin.sh reshape2 plotly knitr
```
2025-10-15 15:04:00 +02:00
This script: - Installs packages in the `course/R_packages/` directory - All students can use them (read-only) - No need to rebuild the image
2025-10-15 07:15:05 +02:00
**From admin notebook:**
Login as `admin` and create an R notebook:
2025-10-15 15:04:00 +02:00
``` r
2025-10-15 14:08:52 +02:00
# Install packages in course/R_packages (admin only, available to all students)
course_lib <- "/home/jovyan/work/course/R_packages"
2025-10-15 07:15:05 +02:00
dir.create(course_lib, recursive = TRUE, showWarnings = FALSE)
install.packages(c('reshape2', 'plotly', 'knitr'),
lib = course_lib,
repos = 'http://cran.rstudio.com/')
```
Note: Admin account has write access to the course directory.
2025-10-15 14:08:52 +02:00
**Students can also install their own packages:**
Students can install packages in their personal `work/R_packages/`:
2025-10-15 15:04:00 +02:00
``` r
2025-10-15 14:08:52 +02:00
# Install in personal library (each student has their own)
install.packages(c('mypackage')) # Will install in work/R_packages/
```
2025-10-15 07:15:05 +02:00
### Using R Packages (Students)
Students simply load packages normally:
2025-10-15 15:04:00 +02:00
``` r
2025-10-15 14:08:52 +02:00
library(reshape2) # R checks: 1) work/R_packages/ 2) work/course/R_packages/ 3) system
2025-10-15 07:15:05 +02:00
library(plotly)
```
2025-10-15 15:04:00 +02:00
R automatically searches in this order: 1. Personal packages: `/home/jovyan/work/R_packages/` (R_LIBS_USER) 2. Prof packages: `/home/jovyan/work/course/R_packages/` (R_LIBS_SITE) 3. System packages
2025-10-15 07:15:05 +02:00
### List Available Packages
2025-10-15 15:04:00 +02:00
``` r
2025-10-15 14:08:52 +02:00
# List all available packages (personal + course + system)
2025-10-15 07:15:05 +02:00
installed.packages()[,"Package"]
2025-10-15 14:08:52 +02:00
# Check personal packages
list.files("/home/jovyan/work/R_packages")
# Check course packages (installed by prof)
list.files("/home/jovyan/work/course/R_packages")
2025-10-15 07:15:05 +02:00
```
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
### Deposit Files for Course
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
To put files in the `course/` directory (accessible read-only):
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
``` bash
2025-10-15 07:10:44 +02:00
# Create a temporary directory
2025-10-14 17:40:41 +02:00
mkdir -p ~/jupyterhub-tp/course-files
2025-10-15 07:10:44 +02:00
# Copy your files into it
cp my_notebooks.ipynb ~/jupyterhub-tp/course-files/
cp my_data.csv ~/jupyterhub-tp/course-files/
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
# Copy into Docker volume
2025-10-14 17:40:41 +02:00
docker run --rm \
-v jupyterhub-course:/target \
-v ~/jupyterhub-tp/course-files:/source \
alpine sh -c "cp -r /source/* /target/"
```
2025-10-15 07:10:44 +02:00
### Access Shared Files Between Students
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
Students can collaborate via the `shared/` directory:
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
``` python
2025-10-15 07:10:44 +02:00
# In a notebook, to read a shared file
2025-10-14 17:40:41 +02:00
import pandas as pd
2025-10-15 14:08:52 +02:00
df = pd.read_csv('/home/jovyan/work/shared/group_data.csv')
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
# To write a shared file
2025-10-15 14:08:52 +02:00
df.to_csv('/home/jovyan/work/shared/alice_results.csv')
2025-10-14 17:40:41 +02:00
```
2025-10-15 07:10:44 +02:00
### Retrieve Student Work
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
``` bash
2025-10-15 07:10:44 +02:00
# List user volumes
2025-10-14 17:40:41 +02:00
docker volume ls | grep jupyterhub-user
2025-10-15 07:10:44 +02:00
# Copy files from a specific student
2025-10-14 17:40:41 +02:00
docker run --rm \
-v jupyterhub-user-alice:/source \
2025-10-15 07:10:44 +02:00
-v ~/submissions:/target \
2025-10-14 17:40:41 +02:00
alpine sh -c "cp -r /source/* /target/alice/"
2025-10-15 07:10:44 +02:00
# Copy all shared work
2025-10-14 17:40:41 +02:00
docker run --rm \
-v jupyterhub-shared:/source \
2025-10-15 07:10:44 +02:00
-v ~/submissions/shared:/target \
2025-10-14 17:40:41 +02:00
alpine sh -c "cp -r /source/* /target/"
```
2025-10-15 07:10:44 +02:00
## User Management
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
### Option 1: Predefined User List
2025-10-15 15:04:00 +02:00
2025-10-15 07:10:44 +02:00
In `jupyterhub_config.py`, uncomment and modify:
2025-10-15 15:04:00 +02:00
``` python
2025-10-15 07:10:44 +02:00
c.Authenticator.allowed_users = {'student1', 'student2', 'student3'}
2025-10-14 17:40:41 +02:00
```
2025-10-15 07:10:44 +02:00
### Option 2: Allow Everyone (for testing)
2025-10-15 15:04:00 +02:00
2025-10-15 07:10:44 +02:00
By default, the configuration allows any user:
2025-10-15 15:04:00 +02:00
``` python
2025-10-14 17:40:41 +02:00
c.Authenticator.allow_all = True
```
2025-10-15 07:10:44 +02:00
⚠️ **Warning**: DummyAuthenticator is ONLY for local testing!
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
## Kernel Verification
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
Once logged in, create a new notebook and verify you have access to: - **Python 3** (default kernel) - **R** (R kernel) - **Bash** (bash kernel)
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
## Customization for Your Labs
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
### Add Additional R Packages
2025-10-15 15:04:00 +02:00
2025-10-15 07:10:44 +02:00
Modify the `Dockerfile` (before `USER ${NB_UID}`):
2025-10-15 15:04:00 +02:00
``` dockerfile
2025-10-15 07:10:44 +02:00
RUN R -e "install.packages(c('your_package'), repos='http://cran.rstudio.com/')"
2025-10-14 17:40:41 +02:00
```
2025-10-15 07:10:44 +02:00
Then rebuild:
2025-10-15 15:04:00 +02:00
``` bash
2025-10-14 17:40:41 +02:00
docker build -t jupyterhub-student:latest -f Dockerfile .
docker-compose restart jupyterhub
```
2025-10-15 07:10:44 +02:00
### Add Python Packages
2025-10-15 15:04:00 +02:00
2025-10-15 07:10:44 +02:00
Add to the `Dockerfile` (before `USER ${NB_UID}`):
2025-10-15 15:04:00 +02:00
``` dockerfile
2025-10-14 17:40:41 +02:00
RUN pip install numpy pandas matplotlib seaborn
```
2025-10-15 07:10:44 +02:00
### Distribute Files to Students
2025-10-15 15:04:00 +02:00
2025-10-15 07:10:44 +02:00
Create a `files_lab/` directory and add to the `Dockerfile`:
2025-10-15 15:04:00 +02:00
``` dockerfile
2025-10-15 07:10:44 +02:00
COPY files_lab/ /home/${NB_USER}/lab/
RUN chown -R ${NB_UID}:${NB_GID} /home/${NB_USER}/lab
2025-10-14 17:40:41 +02:00
```
2025-10-15 07:10:44 +02:00
### Change Port (if 8000 is occupied)
2025-10-15 15:04:00 +02:00
2025-10-15 07:10:44 +02:00
Modify in `docker-compose.yml`:
2025-10-15 15:04:00 +02:00
``` yaml
2025-10-14 17:40:41 +02:00
ports:
2025-10-15 07:10:44 +02:00
- "8001:8000" # Accessible on localhost:8001
2025-10-14 17:40:41 +02:00
```
2025-10-15 07:10:44 +02:00
## Advantages of This Approach
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
**Everything in Docker**: No need to install Python/JupyterHub on your computer\
**Portable**: Easy to deploy on another server\
**Isolated**: No pollution of your system environment\
**Easy to Clean**: A simple `docker-compose down` is enough\
2025-10-15 07:10:44 +02:00
**Reproducible**: Students will have exactly the same environment
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
## Troubleshooting
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
**Error "Cannot connect to Docker daemon"**: - Check that OrbStack is running - Verify the socket exists: `ls -la /var/run/docker.sock`
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
**Student containers don't start**: - Check logs: `docker-compose logs jupyterhub` - Verify student image exists: `docker images | grep jupyterhub-student`
2025-10-14 17:40:41 +02:00
2025-10-15 15:04:00 +02:00
**Port 8000 already in use**: - Change port in `docker-compose.yml`
2025-10-14 17:40:41 +02:00
2025-10-15 07:10:44 +02:00
**After config modification, changes are not applied**:
2025-10-15 15:04:00 +02:00
``` bash
2025-10-14 17:40:41 +02:00
docker-compose restart jupyterhub
```
2025-10-15 07:10:44 +02:00
**I want to start from scratch**:
2025-10-15 15:04:00 +02:00
``` bash
2025-10-14 17:40:41 +02:00
docker-compose down -v
docker rmi jupyterhub-hub jupyterhub-student
2025-10-15 07:10:44 +02:00
# Then rebuild everything
./start-jupyterhub.sh
2025-10-15 15:04:00 +02:00
```