Este artículo describe cómo configurar Jupyter detrás del proxy inverso Nginx, ya que dicha configuración no es muy obvia para muchas personas. Hay muchos problemas y esencias en GitHub, y es difícil elegir la solución adecuada para este problema. Además, puede encontrar muchos artículos diferentes que describen cómo hacerlo, pero la mayoría de ellos están desactualizados y no cubren bien la configuración de CORS.
Como el tema sigue estando de moda, decidí renovar el artículo y simplificar la configuración.
Gracias por sus comentarios a continuación, Andrew Barker . Vea la versión actualizada del artículo.
Configuración de Docker
En esta sección del artículo, cubriremos el caso en el que podría necesitar iniciar Jupyter o JupyterHub en un entorno Docker normal.
Configuración de JupyterHub
Primero, creemos una carpeta donde colocaremos todos nuestros archivos de configuración.
Aquí está nuestra estructura final:
mkdir docker
tree docker
docker
├── docker-compose.yaml
├── jupyter_notebook_config.py
└── nginx.conf
Composición de Docker
Para simplificar todo, creé docker-compose.yaml
, que describe nuestros servicios:
version: "3.7"
services:
nginx:
image: nginx:alpine
volumes:
- "./nginx.conf:/etc/nginx/nginx.conf:ro"
ports:
- 8080:8080
links:
- "jupyterhub"
jupyterhub:
image: jupyterhub/jupyterhub
container_name: jupyterhub
volumes:
- "./jupyter_notebook_config.py:/root/.jupyter/jupyter_notebook_config.py:ro"
La configuración es sencilla:un pequeño contenedor Nginx Docker simple frente a Jupyterhub.
Ambos lanzados desde sus últimas versiones.
Configuración de Nginx
Nginx se encuentra en el puerto 8080 y escuchando en el puerto 8080 también.
MUY IMPORTANTE: nginx.conf
contiene la configuración del proxy inverso.
Si su Nginx está ubicado en un puerto que no sea 80 o 443 , necesita usar la siguiente directiva de configuración:
proxy_set_header Host $host:$server_port;
Para Nginx, que se encuentra en los puertos predeterminados, use default
configuración:
proxy_set_header Host $host;
Si comete un error aquí, comenzará a recibir Blocking Cross Origin API request for /api/contents
mensajes de error.
Una vez más, el motivo principal de estos mensajes no son los puertos iguales para el enlace de servicios y la exportación para contenedores Nginx.
Aquí está mi nginx.conf
para escuchar en el puerto 8080
:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream ml {
server jupyterhub:8000;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8080;
location / {
proxy_pass http://ml;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# websocket headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
Configuración de Jupyter
Para la configuración de JupyterHub, usaremos la siguiente configuración colocada en /root/.jupyter/jupyter_notebook_config.py
:
# get the config object
c = get_config()
# JupyterHub listen address
c.JupyterHub.hub_ip = '0.0.0.0'
# JupyterHub connect hostname.
# In our case it's 'jupyterhub' by the name of the service from docker-compose.yaml
c.JupyterHub.hub_connect_ip = 'jupyterhub'
# Location for users notebooks
c.Spawner.notebook_dir = '~/'
Lanzamiento de Jupyrter detrás de Nginx Proxy
No tuve mucho tiempo para construir un nuevo contenedor y/o jugar con la configuración de autenticación de usuario. El objetivo principal es proporcionar una solución para bloquear solicitudes de API de origen cruzado para /api/contents problemas.
Entonces, así es como puede iniciar esta configuración:
docker-compose up -d
Conéctese a los contenedores recién lanzados, cree un usuario e instale el portátil paquete:
docker exec -it jupyterhub /bin/bash
adduser
pip install notebook
Ahora puede conectarse a JupterHub y usar su nombre de usuario y contraseña creados como credenciales de inicio de sesión.
Configuración de Docker Swarm
En esta sección del artículo, cubriremos el caso en el que podría necesitar iniciar Jupyter o JupyterHub en un modo Docker Swarm.
Modifiquemos ligeramente nuestra carpeta de proyecto:
.
├── .env
├── docker-compose.yaml
├── jupyterhub
│ ├── Dockerfile
│ ├── jupyterhub_config.py
└── nginx
└── nginx.conf
3 directories, 5 files
Composición Docker (Enjambre)
Así es como nuestro docker-compose.yaml
el archivo se verá así:
version: "3.7"
services:
# Configuration for reverse proxy
nginx:
image: nginx:alpine
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
ports:
- 8080:8080
networks:
default:
jupyterhub_network:
aliases:
- nginx
# Configuration for Hub+Proxy
jupyterhub:
env_file: .env
build: jupyterhub
image: jupyterhub_customized
hostname: jupyterhub
volumes:
- "./jupyterhub/jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro"
- "/var/run/docker.sock:/var/run/docker.sock"
ports:
- 8000:8000
networks:
default:
jupyterhub_network:
aliases:
- jupyterhub
environment:
# Name of the Docker image for the single-user servers
DOCKER_JUPYTER_IMAGE: ${DOCKER_JUPYTER_IMAGE}
# The name of the Docker network used by the services
DOCKER_NETWORK_NAME: ${COMPOSE_PROJECT_NAME}_jupyterhub_network
# The IP address of the Hub service within the docker network
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
# Configuration for the single-user servers
jupyterlab:
image: ${DOCKER_JUPYTER_IMAGE}
command: echo
networks:
jupyterhub_network:
driver: overlay
volumes:
jupyterhub_data:
Las variables de entorno de Docker-compose se definen en .env
archivo:
# Name of our Docker Compose project
COMPOSE_PROJECT_NAME="jupyterhub"
DOCKER_JUPYTER_IMAGE="jupyterhub/singleuser:2.2"
Configuración de JupyterHub (enjambre)
Necesitamos crear nuestra propia imagen personalizada de JupyterHub para incluir automáticamente dockerspawner, dummyauthenticator y cualquier otro módulo que pueda necesitar (por ejemplo, para admitir diferentes métodos de autenticación).
# Do not forget to pin down the version
FROM jupyterhub/jupyterhub
# Install dependencies (for advanced authentication and spawning)
RUN pip install \
dockerspawner \
jupyterhub-dummyauthenticator
También debemos proporcionar la configuración correcta para JupyterHub:
import os
NETWORK_NAME = os.environ['DOCKER_NETWORK_NAME']
DOCKER_JUPYTER_IMAGE = os.environ['DOCKER_JUPYTER_IMAGE']
# get the config object
c = get_config()
c.ConfigurableHTTPProxy.should_start = True
c.JupyterHub.authenticator_class = 'dummyauthenticator.DummyAuthenticator'
c.JupyterHub.hub_ip = '0.0.0.0'
c.JupyterHub.hub_connect_ip = 'jupyterhub'
c.JupyterHub.spawner_class = 'dockerspawner.SwarmSpawner'
c.JupyterHub.tornado_settings = {'slow_spawn_timeout': 30}
c.SwarmSpawner.image = DOCKER_JUPYTER_IMAGE
c.SwarmSpawner.network_name = NETWORK_NAME
c.SwarmSpawner.remove_containers = True
c.Spawner.cmd = ["jupyter", "labhub"]
c.Spawner.args = ['--allow-root']
c.Spawner.notebook_dir = '~/'
c.Spawner.debug = True
c.SwarmSpawner.debug = True
c.SwarmSpawner.host_ip = '0.0.0.0'
c.SwarmSpawner.http_timeout = 300
c.SwarmSpawner.start_timeout = 300
#c.JupyterHub.log_level = 00
#c.ConfigurableHTTPProxy.debug = True
Para obtener más información, le recomiendo encarecidamente que consulte los siguientes enlaces:
- Usando SwarmSpawner (ejemplo oficial)
- Documentación oficial de SwarmSpawner (JupyterHub)
- Implementación de un servidor JupyterHub en contenedores con Docker (artículo)
- Cómo ejecutar JupyterHub en un entorno docker swarm usando swarmSpawner (artículo)
Configuración de Nginx (enjambre)
La configuración de Nginx permanecerá sin cambios, pero pongámoslo aquí para completar el ejemplo:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream ml {
server jupyterhub:8000;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8080;
location / {
proxy_pass http://ml;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# websocket headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
Ejemplo de demostración
Para iniciar la demostración proporcionada, ejecute el siguiente comando:
docker-compose build
docker-compose up
Tan pronto como se inicie el servicio, conéctese a la dirección IP externa de su servidor al puerto 8080:
Debería ver el siguiente resultado de la consola:
En el navegador debería ver la siguiente página:
Utilice cualquier nombre de usuario y no proporcione ninguna contraseña. Haga clic en Iniciar sesión y será redirigido al entorno de laboratorio del usuario:
Resumen
Espero que esta pequeña nota te ayude a ahorrar algo de tiempo. Si te resultó útil, ¡ayuda a difundirlo por todo el mundo!
¡Estén atentos!