From 8d9291d31203e1ed9c1c54a24658428e26877ba9 Mon Sep 17 00:00:00 2001
From: DerGrumpf
Date: Mon, 15 Sep 2025 15:31:53 +0200
Subject: [PATCH] Added: Changed DockerSpawner
---
.env_example | 6 +--
jupyterhub/jupyterhub_config.py | 78 +++++++++++----------------------
2 files changed, 28 insertions(+), 56 deletions(-)
diff --git a/.env_example b/.env_example
index d9056ae..0d02285 100644
--- a/.env_example
+++ b/.env_example
@@ -1,6 +1,3 @@
-# THIS IS AN EXAMPLE
-# CHANGE IT IN PRODUCTION
-
# Postgres Setup
POSTGRES_DB=jupyter
POSTGRES_USER=jupyter
@@ -18,8 +15,11 @@ SPAWNER_DEFAULT_URL=/lab
NOTEBOOK_MEMORY_LIMIT=500M
NOTEBOOK_CPU_LIMIT=1.0
HUB_IP=jupyterhub # Name of the Docker container
+DOCKER_NOTEBOOK_DIR=/home/jovyan/work
+DOCKER_SPAWNER_DEBUG=0 # Set to non Zero to enable
# Docker
+COMPOSE_PROJECT_NAME=ifn_stack
DOCKER_NETWORK_NAME=jupyter_network
POSTGRES_PORT=5432
JUPYTERHUB_PORT=8000
diff --git a/jupyterhub/jupyterhub_config.py b/jupyterhub/jupyterhub_config.py
index c55b332..7676a7f 100644
--- a/jupyterhub/jupyterhub_config.py
+++ b/jupyterhub/jupyterhub_config.py
@@ -95,61 +95,44 @@ c.JupyterHub.template_paths = ["/etc/jupyterhub/templates"]
# Hub environment for containers
+
+# Spawn Single-User-Servers as Docker Containers
c.JupyterHub.spawner_class = DockerSpawner
-c.Spawner.ip = "0.0.0.0"
+
+# Spawn Containers from this Image
c.DockerSpawner.image = os.environ.get(
"NOTEBOOK_IMAGE", "jupyter/scipy-notebook:latest"
)
-'''network_name = os.environ.get('DOCKER_NETWORK_NAME', 'stack_default')
-c.DockerSpawner.network_name = network_name
-c.DockerSpawner.extra_host_config = {
- 'network_mode': network_name
-}
-c.DockerSpawner.remove = True
-c.DockerSpawner.debug = True
-c.DockerSpawner.default_url = os.environ.get('SPAWNER_DEFAULT_URL', '/lab')
-c.DockerSpawner.use_internal_ip = True
-# Resources
-c.DockerSpawner.mem_limit = os.environ.get('NOTEBOOK_MEMORY_LIMIT', '500M')
-c.DockerSpawner.cpu_limit = float(os.environ.get('NOTEBOOK_CPU_LIMIT', '1.0'))
+# Connect Containers to this network
+network_name = os.environ.get("DOCKER_NETWORK_NAME", "stack_default")
+c.DockerSpawner.use_internal_ip = True # Let docker manage network communications
+c.DockerSpawner.network_name = network_name
-# Volume
-c.DockerSpawner.volumes = {
- '/var/run/docker.sock': '/var/run/docker.sock'
-# './data/jupyter/users/{username}': '/home/jovyan/work',
-# './data/jupyter/nbgrader/exchange': '/srv/nbgrader/exchange',
-# './data/jupyter/nbgrader/courses': '/srv/nbgrader/courses',
-}
+# Explicitly set notebook directory because we'll mounting a volume to it.
+notebook_dir = os.environ.get("DOCKER_NOTEBOOK_DIR", "/home/jovyan/work")
+c.DockerSpawner.notebook_dir = notebook_dir
-c.DockerSpawner.notebook_dir = '/home/jovyan/work'
+# Mount real User docker volume to the host
+c.DockerSpawner.volumes = {"jupyterhub-user-{username}": notebook_dir}
-# Container Environment
-c.DockerSpawner.environment = {
- 'GRANT_SUDO': '0',
- 'JUPYTER_ENABLE_LAB': os.environ.get('ENABLE_LAB', '1'),
- 'JUPYTERHUB_SINGLEUSER_APP': 'jupyter_server.serverapp.ServerApp'
-}
+# Remove Containers once there stopped
+c.DockerSpawner.remove = True
-#c.DockerSpawner.hub_ip_connect = os.environ.get('HUB_IP', 'jupyterhub')
-#c.DockerSpawner.hub_port_connect = 8081
+# For Debbugging (passed to spawned Containers)
+ds_debug = True if int(os.environ.get("DOCKER_SPAWNER_DEBUG", "0")) else False
+c.DockerSpawner.debug = ds_debug
-def pre_spawn_hook(spawner):
- """Create user directories before spawning"""
- username = spawner.user.name
- user_dir = f"./data/jupyter/users/{username}"
+# Dont mess with this
+# The Spawner sits inside a docker container which manages
+# everything network related
+c.Spawner.ip = "0.0.0.0"
- import os
- import stat
- if not os.path.exists(user_dir):
- os.makedirs(user_dir, mode=0o755, exist_ok=True)
- os.chown(user_dir, 1000, 1000)
+# Set Resource Limits
+c.DockerSpawner.mem_limit = os.environ.get("NOTEBOOK_MEMORY_LIMIT", "500M")
+c.DockerSpawner.cpu_limit = float(os.environ.get("NOTEBOOK_CPU_LIMIT", "1.0"))
- # TODO Nbgrader dirs
-
-c.DockerSpawner.pre_spawn_hook = pre_spawn_hook
-'''
"""
# Services configuration for NBGrader
@@ -223,14 +206,3 @@ c.JupyterHub.concurrent_spawn_limit = 10
# Allow named servers
c.JupyterHub.allow_named_servers = True
c.JupyterHub.named_server_limit_per_user = 3
-
-print("JupyterHub configuration loaded successfully!")
-print(f"Base URL: {c.JupyterHub.base_url}")
-print(f"Bind URL: {c.JupyterHub.bind_url}")
-print(f"Database URL: {c.JupyterHub.db_url}")
-print(f"Docker Network: {c.DockerSpawner.network_name}")
-print(f"Docker Image: {c.DockerSpawner.image}")
-print("Postgres available", is_service_available_cmd("postgres", 5432))
-
-with open("/srv/jupyterhub/cookie_secret") as f:
- print(f.readlines())