Merge pull request 'push-svpkkstsnzoy' (#1) from push-svpkkstsnzoy into push-qlwkxzrrwlkv

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2025-10-15 13:00:00 +00:00
7 changed files with 507 additions and 188 deletions

View File

@@ -1,34 +1,49 @@
FROM jupyter/base-notebook:latest # ---------- Stage 1 : builder ----------
FROM jupyter/base-notebook:latest AS builder
USER root USER root
# Installation de R et des dépendances système # Install system dependencies for R, build tools and Go/Rust
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
r-base \ r-base r-base-dev \
r-base-dev \ libcurl4-openssl-dev libssl-dev libxml2-dev \
libcurl4-openssl-dev \ build-essential git curl \
libssl-dev \
libxml2-dev \
texlive-xetex \
texlive-fonts-recommended \
texlive-plain-generic \
&& apt-get clean && rm -rf /var/lib/apt/lists/* && apt-get clean && rm -rf /var/lib/apt/lists/*
# Installation du kernel R pour Jupyter (en tant que root) # Install R kernel + useful packages
RUN R -e "install.packages('IRkernel', repos='http://cran.rstudio.com/')" && \ RUN R -e "install.packages('IRkernel', repos='http://cran.rstudio.com/')" && \
R -e "IRkernel::installspec(user = FALSE)" R -e "IRkernel::installspec(user = FALSE)" && \
R -e "install.packages(c('tidyverse','vegan','ade4'), repos='http://cran.rstudio.com/')"
# Installation de quelques packages R utiles pour les TP # Install bash kernel
RUN R -e "install.packages(c('tidyverse','vegan','ade4'), repos='http://cran.rstudio.com/')" RUN pip install bash_kernel && python -m bash_kernel.install --sys-prefix
# Installation du kernel bash (en tant que root aussi) # Install obitools4
RUN pip install bash_kernel && \ RUN curl -L https://raw.githubusercontent.com/metabarcoding/obitools4/master/install_obitools.sh | bash
python -m bash_kernel.install --sys-prefix
# Créer les répertoires nécessaires avec les bonnes permissions # Install csvkit
RUN pip install csvkit
# Install csvlens via Rust
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
. $HOME/.cargo/env && \
cargo install csvlens
RUN apt-get update && apt-get install -y ruby ruby-dev build-essential \
&& gem install youplot
# Copy csvlens to /usr/local/bin for final use
RUN cp $HOME/.cargo/bin/csvlens /usr/local/bin/
# Set permissions for Jupyter user
RUN mkdir -p /home/${NB_USER}/.local/share/jupyter && \ RUN mkdir -p /home/${NB_USER}/.local/share/jupyter && \
chown -R ${NB_UID}:${NB_GID} /home/${NB_USER} chown -R ${NB_UID}:${NB_GID} /home/${NB_USER}
USER ${NB_UID} # Switch back to Jupyter user
USER ${NB_UID}:${NB_GID}
WORKDIR /home/${NB_USER}/work
WORKDIR /home/${NB_USER} # Environment variables
ENV PATH="/home/${NB_USER}/work/course/bin:${PATH}"
ENV R_LIBS_USER="/home/${NB_USER}/work/R_packages"
ENV R_LIBS_SITE="/home/${NB_USER}/work/course/R_packages:/usr/local/lib/R/site-library:/usr/lib/R/site-library"

View File

@@ -1,16 +1,16 @@
FROM jupyterhub/jupyterhub:latest FROM jupyterhub/jupyterhub:latest
# Installation de DockerSpawner # Install DockerSpawner
RUN pip install dockerspawner RUN pip install dockerspawner
# Copie de la configuration # Copy configuration
COPY jupyterhub_config.py /srv/jupyterhub/jupyterhub_config.py COPY jupyterhub_config.py /srv/jupyterhub/jupyterhub_config.py
# Port exposé # Expose port
EXPOSE 8000 EXPOSE 8000
# Répertoire de travail # Working directory
WORKDIR /srv/jupyterhub WORKDIR /srv/jupyterhub
# Commande de démarrage # Startup command
CMD ["jupyterhub", "-f", "/srv/jupyterhub/jupyterhub_config.py"] CMD ["jupyterhub", "-f", "/srv/jupyterhub/jupyterhub_config.py"]

314
Readme.md
View File

@@ -1,258 +1,350 @@
# Configuration JupyterHub avec OrbStack sur Mac (tout en Docker) # JupyterHub Configuration with OrbStack on Mac (all in Docker)
## Prérequis ## Prerequisites
- OrbStack installé et démarré - OrbStack installed and running
## Structure des fichiers ## File Structure
Votre dossier `~/jupyterhub-tp` doit contenir : Your `~/jupyterhub-tp` directory should contain:
``` ```
~/jupyterhub-tp/ ~/jupyterhub-tp/
├── Dockerfile # Image pour les étudiants (déjà créée) ├── Dockerfile # Image for students (already created)
├── Dockerfile.hub # Image pour JupyterHub (nouvelle) ├── Dockerfile.hub # Image for JupyterHub (new)
├── jupyterhub_config.py # Configuration ├── jupyterhub_config.py # Configuration
── docker-compose.yml # Orchestration ── docker-compose.yml # Orchestration
└── start-jupyterhub.sh # Startup script
``` ```
## Étapes d'installation ## Installation Steps
### 1. Créer la structure de dossiers ### 1. Create Directory Structure
```bash ```bash
mkdir -p ~/jupyterhub-tp mkdir -p ~/jupyterhub-tp
cd ~/jupyterhub-tp cd ~/jupyterhub-tp
``` ```
### 2. Créer tous les fichiers nécessaires ### 2. Create All Necessary Files
Créez les fichiers suivants avec le contenu des artifacts : Create the following files with the content from artifacts:
- `Dockerfile` (artifact "Dockerfile pour JupyterHub avec R et Bash") - `Dockerfile` (artifact "Dockerfile for JupyterHub with R and Bash")
- `Dockerfile.hub` (artifact "Dockerfile pour le container JupyterHub") - `Dockerfile.hub` (artifact "Dockerfile for JupyterHub container")
- `jupyterhub_config.py` (artifact "Configuration JupyterHub") - `jupyterhub_config.py` (artifact "JupyterHub Configuration")
- `docker-compose.yml` (artifact "docker-compose.yml") - `docker-compose.yml` (artifact "docker-compose.yml")
- `start-jupyterhub.sh` (artifact "start-jupyterhub.sh")
### 3. Construire les images Docker ### 3. Make Startup Script Executable
```bash ```bash
# Image pour les étudiants chmod +x start-jupyterhub.sh
docker build -t jupyterhub-student:latest -f Dockerfile .
# Image pour le hub JupyterHub
docker build -t jupyterhub-hub:latest -f Dockerfile.hub .
``` ```
### 4. Démarrer JupyterHub avec Docker Compose ### 4. Start JupyterHub
```bash ```bash
docker-compose up -d ./start-jupyterhub.sh
``` ```
### 5. Accéder à JupyterHub ### 5. Access JupyterHub
Ouvrez votre navigateur et allez à : **http://localhost:8000** Open your browser and go to: **http://localhost:8888**
Vous pouvez vous connecter avec n'importe quel nom d'utilisateur. You can log in with any username and password: `metabar2025`
## Commandes utiles ## Useful Commands
### Voir les logs de JupyterHub ### View JupyterHub logs
```bash ```bash
docker-compose logs -f jupyterhub docker-compose logs -f jupyterhub
``` ```
### Voir tous les containers (hub + étudiants) ### View all containers (hub + students)
```bash ```bash
docker ps docker ps
``` ```
### Arrêter JupyterHub ### Stop JupyterHub
```bash ```bash
docker-compose down docker-compose down
``` ```
### Redémarrer JupyterHub (après modification du config) ### Restart JupyterHub (after config modification)
```bash ```bash
docker-compose restart jupyterhub docker-compose restart jupyterhub
``` ```
### Reconstruire après modification du Dockerfile ### Rebuild after Dockerfile modification
```bash ```bash
# Pour l'image étudiants # For student image
docker build -t jupyterhub-student:latest -f Dockerfile . docker build -t jupyterhub-student:latest -f Dockerfile .
docker-compose restart jupyterhub docker-compose restart jupyterhub
# Pour l'image hub # For hub image
docker-compose up -d --build docker-compose up -d --build
``` ```
### Voir les logs d'un étudiant spécifique ### View logs for a specific student
```bash ```bash
docker logs jupyter-nom_utilisateur docker logs jupyter-username
``` ```
### Nettoyer après le TP ### Clean up after lab
```bash ```bash
# Arrêter et supprimer tous les containers # Stop and remove all containers
docker-compose down docker-compose down
# Supprimer les containers étudiants # Remove student containers
docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f
# Supprimer les volumes (ATTENTION : supprime les données étudiants) # Remove volumes (WARNING: deletes student data)
docker volume ls | grep jupyterhub-user | awk '{print $2}' | xargs docker volume rm docker volume ls | grep jupyterhub-user | awk '{print $2}' | xargs docker volume rm
# Tout nettoyer (containers + volumes + réseau) # Clean everything (containers + volumes + network)
docker-compose down -v docker-compose down -v
docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f docker ps -a | grep jupyter- | awk '{print $1}' | xargs docker rm -f
docker volume prune -f docker volume prune -f
``` ```
## Gestion des données partagées ## Managing Shared Data
### Structure des dossiers pour chaque étudiant ### Directory Structure for Each Student
Chaque étudiant verra ces dossiers dans son JupyterLab : Each student will see this directory structure in their JupyterLab (everything under `work/` is persistent):
- **`work/`** : Son espace personnel (persistant, privé) ```
- **`shared/`** : Espace partagé entre tous les étudiants (lecture/écriture) work/ # Personal workspace root (persistent)
- **`course/`** : Fichiers du cours (lecture seule, vous déposez les fichiers) ├── [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
```
### Déposer des fichiers pour le cours **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
Pour mettre des fichiers dans le dossier `course/` (accessible en lecture seule) : **Important:** Everything is under `work/`, so all student files are automatically saved in their persistent volume.
### User Accounts
**Admin Account:**
- Username: `admin`
- Password: `admin2025` (change in docker-compose.yml: `JUPYTERHUB_ADMIN_PASSWORD`)
- Can write to `course/` directory
**Student Accounts:**
- Username: any name
- Password: `metabar2025` (change in docker-compose.yml: `JUPYTERHUB_PASSWORD`)
- Read-only access to `course/` directory
### Installing R Packages (Admin Only)
**From your Mac (recommended):**
```bash ```bash
# Créer un dossier temporaire chmod +x install-r-packages-admin.sh
# Install packages
./install-r-packages-admin.sh reshape2 plotly knitr
```
This script:
- Installs packages in the `course/R_packages/` directory
- All students can use them (read-only)
- No need to rebuild the image
**From admin notebook:**
Login as `admin` and create an R notebook:
```r
# Install packages in course/R_packages (admin only, available to all students)
course_lib <- "/home/jovyan/work/course/R_packages"
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.
**Students can also install their own packages:**
Students can install packages in their personal `work/R_packages/`:
```r
# Install in personal library (each student has their own)
install.packages(c('mypackage')) # Will install in work/R_packages/
```
### Using R Packages (Students)
Students simply load packages normally:
```r
library(reshape2) # R checks: 1) work/R_packages/ 2) work/course/R_packages/ 3) system
library(plotly)
```
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
### List Available Packages
```r
# List all available packages (personal + course + system)
installed.packages()[,"Package"]
# Check personal packages
list.files("/home/jovyan/work/R_packages")
# Check course packages (installed by prof)
list.files("/home/jovyan/work/course/R_packages")
```
### Deposit Files for Course
To put files in the `course/` directory (accessible read-only):
```bash
# Create a temporary directory
mkdir -p ~/jupyterhub-tp/course-files mkdir -p ~/jupyterhub-tp/course-files
# Copier vos fichiers dedans # Copy your files into it
cp mes_notebooks.ipynb ~/jupyterhub-tp/course-files/ cp my_notebooks.ipynb ~/jupyterhub-tp/course-files/
cp mes_donnees.csv ~/jupyterhub-tp/course-files/ cp my_data.csv ~/jupyterhub-tp/course-files/
# Copier dans le volume Docker # Copy into Docker volume
docker run --rm \ docker run --rm \
-v jupyterhub-course:/target \ -v jupyterhub-course:/target \
-v ~/jupyterhub-tp/course-files:/source \ -v ~/jupyterhub-tp/course-files:/source \
alpine sh -c "cp -r /source/* /target/" alpine sh -c "cp -r /source/* /target/"
``` ```
### Accéder aux fichiers partagés entre étudiants ### Access Shared Files Between Students
Les étudiants peuvent collaborer via le dossier `shared/` : Students can collaborate via the `shared/` directory:
```python ```python
# Dans un notebook, pour lire un fichier partagé # In a notebook, to read a shared file
import pandas as pd import pandas as pd
df = pd.read_csv('/home/jovyan/shared/donnees_groupe.csv') df = pd.read_csv('/home/jovyan/work/shared/group_data.csv')
# Pour écrire un fichier partagé # To write a shared file
df.to_csv('/home/jovyan/shared/resultats_alice.csv') df.to_csv('/home/jovyan/work/shared/alice_results.csv')
``` ```
### Récupérer les travaux des étudiants ### Retrieve Student Work
```bash ```bash
# Lister les volumes utilisateurs # List user volumes
docker volume ls | grep jupyterhub-user docker volume ls | grep jupyterhub-user
# Copier les fichiers d'un étudiant spécifique # Copy files from a specific student
docker run --rm \ docker run --rm \
-v jupyterhub-user-alice:/source \ -v jupyterhub-user-alice:/source \
-v ~/rendus:/target \ -v ~/submissions:/target \
alpine sh -c "cp -r /source/* /target/alice/" alpine sh -c "cp -r /source/* /target/alice/"
# Copier tous les travaux partagés # Copy all shared work
docker run --rm \ docker run --rm \
-v jupyterhub-shared:/source \ -v jupyterhub-shared:/source \
-v ~/rendus/shared:/target \ -v ~/submissions/shared:/target \
alpine sh -c "cp -r /source/* /target/" alpine sh -c "cp -r /source/* /target/"
``` ```
## Gestion des utilisateurs ## User Management
### Option 1 : Liste d'utilisateurs prédéfinis ### Option 1: Predefined User List
Dans `jupyterhub_config.py`, commentez et modifiez : In `jupyterhub_config.py`, uncomment and modify:
```python ```python
c.Authenticator.allowed_users = {'etudiant1', 'etudiant2', 'etudiant3'} c.Authenticator.allowed_users = {'student1', 'student2', 'student3'}
``` ```
### Option 2 : Autoriser tout le monde (pour tests) ### Option 2: Allow Everyone (for testing)
Par défaut, la configuration autorise n'importe quel utilisateur : By default, the configuration allows any user:
```python ```python
c.Authenticator.allow_all = True c.Authenticator.allow_all = True
``` ```
⚠️ **Attention** : DummyAuthenticator est UNIQUEMENT pour les tests locaux ! ⚠️ **Warning**: DummyAuthenticator is ONLY for local testing!
## rification des kernels ## Kernel Verification
Une fois connecté, créez un nouveau notebook et vérifiez que vous avez accès à : Once logged in, create a new notebook and verify you have access to:
- **Python 3** (kernel par défaut) - **Python 3** (default kernel)
- **R** (kernel R) - **R** (R kernel)
- **Bash** (kernel bash) - **Bash** (bash kernel)
## Personnalisation pour vos TP ## Customization for Your Labs
### Ajouter des packages R supplémentaires ### Add Additional R Packages
Modifiez le `Dockerfile` (avant `USER ${NB_UID}`) : Modify the `Dockerfile` (before `USER ${NB_UID}`):
```dockerfile ```dockerfile
RUN R -e "install.packages(c('votre_package'), repos='http://cran.rstudio.com/')" RUN R -e "install.packages(c('your_package'), repos='http://cran.rstudio.com/')"
``` ```
Puis reconstruisez : Then rebuild:
```bash ```bash
docker build -t jupyterhub-student:latest -f Dockerfile . docker build -t jupyterhub-student:latest -f Dockerfile .
docker-compose restart jupyterhub docker-compose restart jupyterhub
``` ```
### Ajouter des packages Python ### Add Python Packages
Ajoutez dans le `Dockerfile` (avant `USER ${NB_UID}`) : Add to the `Dockerfile` (before `USER ${NB_UID}`):
```dockerfile ```dockerfile
RUN pip install numpy pandas matplotlib seaborn RUN pip install numpy pandas matplotlib seaborn
``` ```
### Distribuer des fichiers aux étudiants ### Distribute Files to Students
Créez un dossier `files_tp/` et ajoutez dans le `Dockerfile` : Create a `files_lab/` directory and add to the `Dockerfile`:
```dockerfile ```dockerfile
COPY files_tp/ /home/${NB_USER}/tp/ COPY files_lab/ /home/${NB_USER}/lab/
RUN chown -R ${NB_UID}:${NB_GID} /home/${NB_USER}/tp RUN chown -R ${NB_UID}:${NB_GID} /home/${NB_USER}/lab
``` ```
### Changer le port (si 8000 est occupé) ### Change Port (if 8000 is occupied)
Modifiez dans `docker-compose.yml` : Modify in `docker-compose.yml`:
```yaml ```yaml
ports: ports:
- "8001:8000" # Accessible sur localhost:8001 - "8001:8000" # Accessible on localhost:8001
``` ```
## Avantages de cette approche ## Advantages of This Approach
**Tout en Docker** : Plus besoin d'installer Python/JupyterHub sur votre Mac **Everything in Docker**: No need to install Python/JupyterHub on your Mac
**Portable** : Facile à déployer sur un autre Mac ou serveur **Portable**: Easy to deploy on another Mac or server
**Isolé** : Pas de pollution de votre environnement système **Isolated**: No pollution of your system environment
**Facile à nettoyer** : Un simple `docker-compose down` suffit **Easy to Clean**: A simple `docker-compose down` is enough
**Reproductible** : Les étudiants auront exactement le même environnement **Reproducible**: Students will have exactly the same environment
## Dépannage ## Troubleshooting
**Erreur "Cannot connect to Docker daemon"** : **Error "Cannot connect to Docker daemon"**:
- Vérifiez qu'OrbStack est démarré - Check that OrbStack is running
- Vérifiez que le socket existe : `ls -la /var/run/docker.sock` - Verify the socket exists: `ls -la /var/run/docker.sock`
**Les containers étudiants ne démarrent pas** : **Student containers don't start**:
- Vérifiez les logs : `docker-compose logs jupyterhub` - Check logs: `docker-compose logs jupyterhub`
- Vérifiez que l'image étudiants existe : `docker images | grep jupyterhub-student` - Verify student image exists: `docker images | grep jupyterhub-student`
**Port 8000 déjà utilisé** : **Port 8000 already in use**:
- Changez le port dans `docker-compose.yml` - Change port in `docker-compose.yml`
**Après modification du config, les changements ne sont pas pris en compte** : **After config modification, changes are not applied**:
```bash ```bash
docker-compose restart jupyterhub docker-compose restart jupyterhub
``` ```
**Je veux repartir de zéro** : **I want to start from scratch**:
```bash ```bash
docker-compose down -v docker-compose down -v
docker rmi jupyterhub-hub jupyterhub-student docker rmi jupyterhub-hub jupyterhub-student
# Puis reconstruire tout # Then rebuild everything
``` ./start-jupyterhub.sh
```

View File

@@ -8,19 +8,21 @@ services:
ports: ports:
- "8888:8000" - "8888:8000"
volumes: volumes:
# Accès au socket Docker pour spawner les containers étudiants # Access to Docker socket to spawn student containers
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
# Persistance de la base de données JupyterHub # JupyterHub database persistence
- jupyterhub-data:/srv/jupyterhub - jupyterhub-data:/srv/jupyterhub
# Montage du fichier de config en direct (pour modifications faciles) # Mount config file directly (for easy modifications)
- ./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro - ./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro
networks: networks:
- jupyterhub-network - jupyterhub-network
restart: unless-stopped restart: unless-stopped
environment: environment:
# Mot de passe partagé pour tous les étudiants # Shared password for all students
JUPYTERHUB_PASSWORD: metabar2025 JUPYTERHUB_PASSWORD: metabar2025
# Variables d'environnement optionnelles # Admin password (for installing R packages)
JUPYTERHUB_ADMIN_PASSWORD: admin2025
# Optional environment variables
DOCKER_NOTEBOOK_DIR: /home/jovyan/work DOCKER_NOTEBOOK_DIR: /home/jovyan/work
networks: networks:
@@ -31,4 +33,5 @@ networks:
volumes: volumes:
jupyterhub-data: jupyterhub-data:
jupyterhub-shared: jupyterhub-shared:
jupyterhub-course: jupyterhub-course:

74
install_packages.sh Normal file
View File

@@ -0,0 +1,74 @@
#!/bin/bash
# Script to install R packages in the course directory (admin only)
# Usage: ./install-r-packages.sh package1 package2 package3
set -e
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${BLUE}📦 R Package Installer (Admin)${NC}"
echo "================================"
echo ""
# Check if packages are provided
if [ $# -eq 0 ]; then
echo -e "${RED}❌ Error: No packages specified${NC}"
echo ""
echo "Usage:"
echo " ./install-r-packages.sh package1 package2 package3"
echo ""
echo "Example:"
echo " ./install-r-packages.sh reshape2 plotly knitr"
exit 1
fi
# Build package list
PACKAGES=$(IFS=,; echo "$*")
R_PACKAGES=$(echo "$PACKAGES" | sed "s/,/', '/g")
echo -e "${YELLOW}📋 Packages to install: ${R_PACKAGES}${NC}"
echo ""
# Create a temporary directory for installation
TEMP_DIR=$(mktemp -d)
echo -e "${BLUE}📁 Creating temporary directory: ${TEMP_DIR}${NC}"
# Install packages in temporary directory
echo -e "${BLUE}🔨 Installing R packages...${NC}"
docker run --rm \
--user root \
-v "${TEMP_DIR}:/temp_packages" \
jupyterhub-student:latest \
R -e "install.packages(c('${R_PACKAGES}'), lib='/temp_packages', repos='http://cran.rstudio.com/')" || {
echo -e "${RED}❌ Failed to install packages${NC}"
rm -rf "${TEMP_DIR}"
exit 1
}
# Copy to course R packages directory
echo ""
echo -e "${BLUE}💾 Copying to course/R_packages...${NC}"
docker run --rm \
-v jupyterhub-course:/target \
-v "${TEMP_DIR}:/source" \
alpine sh -c "mkdir -p /target/R_packages && cp -r /source/* /target/R_packages/"
# Clean up
rm -rf "${TEMP_DIR}"
# List installed packages
echo ""
echo -e "${GREEN}✅ Installation complete!${NC}"
echo ""
echo -e "${BLUE}📦 Installed packages in work/course/R_packages:${NC}"
docker run --rm \
-v jupyterhub-course:/course \
alpine ls -1 /course/R_packages/
echo ""
echo -e "${YELLOW} Students need to restart their R kernels to use new packages.${NC}"

View File

@@ -1,5 +1,100 @@
import os import os
# Base configuration
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
# Enable debug logs
c.JupyterHub.log_level = 'DEBUG'
c.Spawner.debug = True
# Docker image to use for student containers
c.DockerSpawner.image = 'jupyterhub-student:latest'
# Docker network (create with: docker network create jupyterhub-network)
c.DockerSpawner.network_name = 'jupyterhub-network'
# Connection to OrbStack Docker socket from the hub container
c.DockerSpawner.client_kwargs = {'base_url': 'unix:///var/run/docker.sock'}
# IMPORTANT: Internal URL for communication between containers
# The hub container communicates with user containers via Docker network
c.JupyterHub.hub_ip = '0.0.0.0'
c.JupyterHub.hub_connect_ip = 'jupyterhub'
# Network configuration for student containers
c.DockerSpawner.use_internal_ip = True
c.DockerSpawner.network_name = 'jupyterhub-network'
c.DockerSpawner.extra_host_config = {'network_mode': 'jupyterhub-network'}
# Remove containers after disconnection (optional, set to False to keep containers)
c.DockerSpawner.remove = True
# Container naming
c.DockerSpawner.name_template = "jupyter-{username}"
# Volume mounting to persist student data
# Set root to work/ - everything is persistent
notebook_dir = '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir
# Personal volume for each student + shared volumes under work/
c.DockerSpawner.volumes = {
# Personal volume (persistent) - root directory
'jupyterhub-user-{username}': '/home/jovyan/work',
# Shared volume between all students - under work/
'jupyterhub-shared': '/home/jovyan/work/shared',
# Shared read-only volume for course files - under work/
'jupyterhub-course': {
'bind': '/home/jovyan/work/course',
'mode': 'ro' # read-only
}
}
# Memory and CPU configuration (adjust according to your needs)
c.DockerSpawner.mem_limit = '2G'
c.DockerSpawner.cpu_limit = 1.0
# User configuration - Simple password authentication for lab
from jupyterhub.auth import DummyAuthenticator
class SimplePasswordAuthenticator(DummyAuthenticator):
"""Simple authenticator with a shared password for everyone"""
def check_allowed(self, username, authentication=None):
"""Check if user is allowed"""
if authentication is None:
return False
provided_password = authentication.get('password', '')
# Admin user with special password
if username == 'admin':
admin_password = os.environ.get('JUPYTERHUB_ADMIN_PASSWORD', 'admin2025')
return provided_password == admin_password
# Regular students with shared password
student_password = os.environ.get('JUPYTERHUB_PASSWORD', 'metabar2025')
return provided_password == student_password
c.JupyterHub.authenticator_class = SimplePasswordAuthenticator
# To create a list of allowed users, uncomment and modify:
# c.Authenticator.allowed_users = {'student1', 'student2', 'student3'}
# Or allow any user with the correct password:
c.Authenticator.allow_all = True
# Admin configuration
c.Authenticator.admin_users = {'admin'}
# Listening port
c.JupyterHub.bind_url = 'http://0.0.0.0:8000'
# Timeout
c.Spawner.start_timeout = 300
c.Spawner.http_timeout = 120
import os
# Configuration de base # Configuration de base
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner' c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
@@ -34,7 +129,7 @@ c.DockerSpawner.name_template = "jupyter-{username}"
# Montage de volumes pour persister les données des étudiants # Montage de volumes pour persister les données des étudiants
# Définir la racine à /home/jovyan pour voir tous les dossiers # Définir la racine à /home/jovyan pour voir tous les dossiers
notebook_dir = '/home/jovyan' notebook_dir = '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir c.DockerSpawner.notebook_dir = notebook_dir
# Volume personnel pour chaque étudiant + volume partagé # Volume personnel pour chaque étudiant + volume partagé
@@ -42,10 +137,10 @@ c.DockerSpawner.volumes = {
# Volume personnel (persistant) - monté dans work/ # Volume personnel (persistant) - monté dans work/
'jupyterhub-user-{username}': '/home/jovyan/work', 'jupyterhub-user-{username}': '/home/jovyan/work',
# Volume partagé entre tous les étudiants # Volume partagé entre tous les étudiants
'jupyterhub-shared': '/home/jovyan/shared', 'jupyterhub-shared': '/home/jovyan/work/shared',
# Volume partagé en lecture seule pour les fichiers du cours (optionnel) # Volume partagé en lecture seule pour les fichiers du cours (optionnel)
'jupyterhub-course': { 'jupyterhub-course': {
'bind': '/home/jovyan/course', 'bind': '/home/jovyan/work/course',
'mode': 'ro' # read-only 'mode': 'ro' # read-only
} }
} }
@@ -54,26 +149,6 @@ c.DockerSpawner.volumes = {
c.DockerSpawner.mem_limit = '2G' c.DockerSpawner.mem_limit = '2G'
c.DockerSpawner.cpu_limit = 1.0 c.DockerSpawner.cpu_limit = 1.0
# Configuration des utilisateurs - Mot de passe simple pour TP
from jupyterhub.auth import DummyAuthenticator
class SimplePasswordAuthenticator(DummyAuthenticator):
"""Authentificateur simple avec un mot de passe partagé pour tous"""
def check_allowed(self, username, authentication=None):
"""Vérifie si l'utilisateur est autorisé"""
if authentication is None:
return False
# Récupérer le mot de passe depuis la variable d'environnement
expected_password = os.environ.get('JUPYTERHUB_PASSWORD', 'metabar2025')
provided_password = authentication.get('password', '')
# Vérifier le mot de passe
return provided_password == expected_password
c.JupyterHub.authenticator_class = SimplePasswordAuthenticator
# Pour créer une liste d'utilisateurs autorisés, décommentez et modifiez: # Pour créer une liste d'utilisateurs autorisés, décommentez et modifiez:
# c.Authenticator.allowed_users = {'etudiant1', 'etudiant2', 'etudiant3'} # c.Authenticator.allowed_users = {'etudiant1', 'etudiant2', 'etudiant3'}

104
setup.sh Normal file → Executable file
View File

@@ -1,30 +1,90 @@
#!/usr/bin/env bash #!/bin/bash
set -e
# === Variables === # JupyterHub startup script for labs
WORKDIR="$PWD" # Usage: ./start-jupyterhub.sh
NETWORK="jupyterhub-net"
HUB_IMAGE="jupyterhub-hub"
USER_IMAGE="jupyter-tp-singleuser"
# === Préparation === set -e # Stop on error
mkdir -p "$WORKDIR"
cd "$WORKDIR"
echo "[1/5] Création du réseau Docker..." echo "🚀 Starting JupyterHub for Lab"
docker network inspect $NETWORK >/dev/null 2>&1 || docker network create $NETWORK echo "=============================="
echo ""
echo "[2/5] Construction des images..." # Colors for display
docker build -t $USER_IMAGE -f Dockerfile . GREEN='\033[0;32m'
docker build -t $HUB_IMAGE -f Dockerfile.hub . BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo "[3/5] Lancement de JupyterHub..." # Check we're in the right directory
docker compose up -d if [ ! -f "Dockerfile" ] || [ ! -f "docker-compose.yml" ]; then
echo "❌ Error: Run this script from the jupyterhub-tp/ directory"
exit 1
fi
echo "[4/5] Hub accessible sur http://localhost:8888" # Stop existing containers
echo " Login avec n'importe quel nom et mot de passe : metabar2025" echo -e "${BLUE}📦 Stopping existing containers...${NC}"
docker-compose down 2>/dev/null || true
echo "[5/5] Pour voir les utilisateurs actifs :" # Remove old student containers
echo " docker ps | grep jupyterhub-user" echo -e "${BLUE}🧹 Cleaning up student containers...${NC}"
docker ps -aq --filter name=jupyter- | xargs -r docker rm -f 2>/dev/null || true
echo "Terminé." # Build student image
echo ""
echo -e "${BLUE}🔨 Building student image...${NC}"
docker build -t jupyterhub-student:latest -f Dockerfile .
# Build hub image
echo ""
echo -e "${BLUE}🔨 Building JupyterHub image...${NC}"
docker build -t jupyterhub-hub:latest -f Dockerfile.hub .
# Create volumes if they don't exist
echo ""
echo -e "${BLUE}💾 Creating shared volumes...${NC}"
docker volume create jupyterhub-shared 2>/dev/null || echo " Volume jupyterhub-shared already exists"
docker volume create jupyterhub-course 2>/dev/null || echo " Volume jupyterhub-course already exists"
# Start the stack
echo ""
echo -e "${BLUE}🚀 Starting JupyterHub...${NC}"
docker-compose up -d
# Wait for service to be ready
echo ""
echo -e "${YELLOW}⏳ Waiting for JupyterHub to start...${NC}"
sleep 3
# Check that container is running
if docker ps | grep -q jupyterhub; then
echo ""
echo -e "${GREEN}✅ JupyterHub is running!${NC}"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "${GREEN}🌐 JupyterHub available at: http://localhost:8888${NC}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "📝 Password: metabar2025"
echo "👥 Students can connect with any username"
echo ""
echo "🔑 Admin account:"
echo " Username: admin"
echo " Password: admin2025"
echo ""
echo "📂 Each student will have access to:"
echo " - work/ : personal workspace (everything saved)"
echo " - work/R_packages/ : personal R packages (writable)"
echo " - work/shared/ : shared workspace"
echo " - work/course/ : course files (read-only)"
echo " - work/course/R_packages/ : shared R packages by prof (read-only)"
echo " - work/course/bin/ : shared executables (in PATH)"
echo ""
echo "🔍 To view logs: docker-compose logs -f jupyterhub"
echo "🛑 To stop: docker-compose down"
echo ""
else
echo ""
echo -e "${YELLOW}⚠️ JupyterHub container doesn't seem to be starting${NC}"
echo "Check logs with: docker-compose logs jupyterhub"
exit 1
fi