From 2d183995ee829bb5130c53e0b7c53cd21714a1a1 Mon Sep 17 00:00:00 2001 From: Brian Walsh Date: Thu, 11 Jul 2019 01:03:13 +0000 Subject: [PATCH] Adds jupyterhub support --- .dockerignore | 1 + docker-compose.yml | 135 +++++++++++------- jupyterhub/Dockerfile | 14 ++ jupyterlab/Dockerfile | 9 ++ nginx/etc/nginx/grip.conf | 4 +- nginx/etc/nginx/nginx.conf | 1 + .../nginx/sites-enabled/bmeg-jupyter.ddns.net | 43 ++++++ 7 files changed, 155 insertions(+), 52 deletions(-) create mode 100644 .dockerignore create mode 100644 jupyterhub/Dockerfile create mode 100644 jupyterlab/Dockerfile create mode 100644 nginx/etc/nginx/sites-enabled/bmeg-jupyter.ddns.net diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8fce603 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +data/ diff --git a/docker-compose.yml b/docker-compose.yml index b6d1527..1373099 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -48,8 +48,10 @@ services: # specific sites - ./nginx/etc/nginx/sites-enabled/bmegio.ohsu.edu:/etc/nginx/sites-enabled/bmegio.ohsu.edu:ro - ./nginx/etc/nginx/sites-enabled/gen3-ohsu.ddns.net:/etc/nginx/sites-enabled/gen3-ohsu.ddns.net:ro + - ./nginx/etc/nginx/sites-enabled/bmeg-jupyter.ddns.net:/etc/nginx/sites-enabled/bmeg-jupyter.ddns.net:ro - ./nginx/etc/nginx/sites-enabled/bmeg.io:/etc/nginx/sites-enabled/bmeg.io:ro + # for letsencrypt - ./data/certbot/conf:/etc/letsencrypt - ./data/certbot/www:/var/www/certbot @@ -59,6 +61,7 @@ services: depends_on: - grip + - jupyterhub # for letsencrypt @@ -86,60 +89,92 @@ services: - grip - mongo - - # https://github.com/jupyterhub/jupyterhub-deploy-docker - # jupyterhub database - hub-db: - image: postgres:9.5 - container_name: jupyterhub-db - restart: always - environment: - POSTGRES_DB: ${POSTGRES_DB} - PGDATA: ${DB_VOLUME_CONTAINER} - env_file: - - secrets/jupyter.env - volumes: - - "db:${DB_VOLUME_CONTAINER}" - - # jupyterhub - hub: - depends_on: - - hub-db - build: - context: jupyterhub - args: - JUPYTERHUB_VERSION: ${JUPYTERHUB_VERSION} - restart: always - image: jupyterhub - container_name: jupyterhub - volumes: - # Bind Docker socket on the host so we can connect to the daemon from - # within the container - - "/var/run/docker.sock:/var/run/docker.sock:rw" - # Bind Docker volume on host for JupyterHub database and cookie secrets - - "data:${DATA_VOLUME_CONTAINER}" + # see https://opendreamkit.org/2018/10/17/jupyterhub-docker/ + jupyterhub: + build: jupyterhub # Build the container from this folder. + container_name: jupyterhub # The service will use this container name. + volumes: # Give access to Docker socket. + - /var/run/docker.sock:/var/run/docker.sock + # - ./data/certbot/conf/live/bmegio.ohsu.edu/cert.pem:/etc/letsencrypt/cert.pem + # - ./data/certbot/conf/live/bmegio.ohsu.edu/privkey.pem:/etc/letsencrypt/privkey.pem + - ./secrets/userlist:/srv/jupyterhub/userlist - ./secrets/jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py - ports: - - "443:443" - links: - - hub-db - environment: - POSTGRES_HOST: hub-db + - /mnt/data1/bmeg/jupyter-data:/data + environment: # Env variables passed to the Hub process. + DOCKER_NOTEBOOK_IMAGE: jupyterlab_img + DOCKER_NETWORK_NAME: deployment_default + HUB_IP: jupyterhub + # SSL_KEY: /etc/letsencrypt/privkey.pem + # SSL_CERT: /etc/letsencrypt/cert.pem env_file: - secrets/jupyter.env - secrets/oauth.env - command: > - jupyterhub -f /srv/jupyterhub/jupyterhub_config.py - -# docker volume create --name=jupyterhub-data -# docker volume create --name=jupyterhub-db-data -volumes: - data: - external: - name: ${DATA_VOLUME_HOST} - db: - external: - name: ${DB_VOLUME_HOST} + depends_on: + - grip + + # notebook image, build via: `dc build jupyterlab` + # The extra line command: echo is there so that, + # when Docker Compose starts the service, it terminates immediately. + # Indeed this image is meant to be loaded by the Hub, not by Compose. + jupyterlab: + build: jupyterlab + image: jupyterlab_img + command: echo + + +# # https://github.com/jupyterhub/jupyterhub-deploy-docker +# # jupyterhub database +# hub-db: +# image: postgres:9.5 +# container_name: jupyterhub-db +# restart: always +# environment: +# POSTGRES_DB: ${POSTGRES_DB} +# PGDATA: ${DB_VOLUME_CONTAINER} +# env_file: +# - secrets/jupyter.env +# volumes: +# - "db:${DB_VOLUME_CONTAINER}" +# +# # jupyterhub +# hub: +# depends_on: +# - hub-db +# build: +# context: jupyterhub +# args: +# JUPYTERHUB_VERSION: ${JUPYTERHUB_VERSION} +# # restart: always +# # image: jupyterhub +# container_name: jupyterhub +# volumes: +# # Bind Docker socket on the host so we can connect to the daemon from +# # within the container +# - "/var/run/docker.sock:/var/run/docker.sock:rw" +# # Bind Docker volume on host for JupyterHub database and cookie secrets +# - "data:${DATA_VOLUME_CONTAINER}" +# # - ./secrets/jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py +# ports: +# - "443:443" +# links: +# - hub-db +# environment: +# POSTGRES_HOST: hub-db +# env_file: +# - secrets/jupyter.env +# - secrets/oauth.env +# command: > +# jupyterhub -f /srv/jupyterhub/jupyterhub_config.py +# +# # docker volume create --name=jupyterhub-data +# # docker volume create --name=jupyterhub-db-data +# volumes: +# data: +# external: +# name: ${DATA_VOLUME_HOST} +# db: +# external: +# name: ${DB_VOLUME_HOST} # networks: # default: diff --git a/jupyterhub/Dockerfile b/jupyterhub/Dockerfile new file mode 100644 index 0000000..64c6a29 --- /dev/null +++ b/jupyterhub/Dockerfile @@ -0,0 +1,14 @@ +# Do not forget to pin down the version +FROM jupyterhub/jupyterhub:1.0.0 + +# OLD: Copy the JupyterHub configuration in the container + # COPY jupyterhub_config.py . +# NEW: map as volume -> /srv/jupyterhub/jupyterhub_config.py + +# Download script to automatically stop idle single-user servers +RUN wget https://raw.githubusercontent.com/jupyterhub/jupyterhub/1.0.0/examples/cull-idle/cull_idle_servers.py + +# Install dependencies (for advanced authentication and spawning) +RUN pip install \ + dockerspawner==0.11.1 \ + oauthenticator==0.8.2 diff --git a/jupyterlab/Dockerfile b/jupyterlab/Dockerfile new file mode 100644 index 0000000..cd9561c --- /dev/null +++ b/jupyterlab/Dockerfile @@ -0,0 +1,9 @@ +FROM jupyter/scipy-notebook:6c3390a9292e +RUN pip install --pre jupyterhub==1.0.0 + +# RUN pip install jupyterhub==1.0.0 + +# RUN conda install --quiet --yes \ +# 'r-base=3.4.1' \ +# 'r-irkernel=0.8*'&& \ +# conda clean -tipsy diff --git a/nginx/etc/nginx/grip.conf b/nginx/etc/nginx/grip.conf index d5702cb..5daf325 100644 --- a/nginx/etc/nginx/grip.conf +++ b/nginx/etc/nginx/grip.conf @@ -3,7 +3,7 @@ ## lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; lua_ssl_verify_depth 5; - + set_by_lua $ngo_callback_host ' if os.getenv("NGO_CALLBACK_HOST") then return os.getenv("NGO_CALLBACK_HOST") @@ -54,7 +54,7 @@ # our protected "landing page" location /analyze/access { include /etc/nginx/protected.conf; - root /usr/share/nginx/html; + root /usr/share/nginx/bmegio.ohsu.edu; try_files $uri $uri/index.html $uri.html =404; } location /grip/ { diff --git a/nginx/etc/nginx/nginx.conf b/nginx/etc/nginx/nginx.conf index 651ec19..ef652ae 100644 --- a/nginx/etc/nginx/nginx.conf +++ b/nginx/etc/nginx/nginx.conf @@ -92,4 +92,5 @@ http { include /etc/nginx/sites-enabled/bmeg.io; include /etc/nginx/sites-enabled/bmegio.ohsu.edu; include /etc/nginx/sites-enabled/gen3-ohsu.ddns.net; + include /etc/nginx/sites-enabled/bmeg-jupyter.ddns.net; } diff --git a/nginx/etc/nginx/sites-enabled/bmeg-jupyter.ddns.net b/nginx/etc/nginx/sites-enabled/bmeg-jupyter.ddns.net new file mode 100644 index 0000000..e2881a8 --- /dev/null +++ b/nginx/etc/nginx/sites-enabled/bmeg-jupyter.ddns.net @@ -0,0 +1,43 @@ +# top-level http config for websocket headers +# If Upgrade is defined, Connection = upgrade +# If Upgrade is empty, Connection = close +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + + +# redirect to https +server { + listen *:80; + server_name bmeg-jupyter.ddns.net; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name bmeg-jupyter.ddns.net; + ssl_certificate /etc/letsencrypt/live/bmeg-jupyter.ddns.net/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/bmeg-jupyter.ddns.net/privkey.pem; + + + # Managing literal requests to the JupyterHub front end + location / { + proxy_pass http://jupyterhub:8000; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # websocket headers + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + + # for certbot challenge + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + +}