No outside network access for Jupyter Notebook container spawned by JupyterHub

So, here is what I am trying to achieve:

  • A Jupyterhub server
  • Which when accessed and you are not logged in, takes you to another web server (custom coded in Django)
  • That web server uses OAuth to authenticate a user
  • And a notebook container is spawned.
  • This notebook container must be pre-populated with a token that is used by a custom library baked into the notebook Docker image to authenticate against a service.
  • The notebook container needs to be able to communicate with the web server for further interactions like retrieve results etc.

I have more or less achieved this except for the last part. I am getting a notebook server started but it has no access to the outside world. It can only access the Jupyter Hub (that’s why it works!) and nothing else.

Here is my Jupyter Hub config relevant to the DockerSpawner (I’m leaving out the OAuth settings since these work as expected.

# Tell JupyterHub that we want Docker Spawner to be used.
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'

# And what image should be used by the Docker Spawner
c.DockerSpawner.image = 'jupyter/scipy-notebook:7a0c7325e470'

# The Hub must listen on all interfaces.
c.JupyterHub.hub_ip = '0.0.0.0'

# And this should be the address of the Hub API
c.JupyterHub.hub_connect_ip = 'jupyterhub'

# Ask containers to connect to this network so that they can
# communicate with the Hub.
c.DockerSpawner.network_name = 'djangodockerjupyterdemo_default'

# And let's not make a mess, remove user containers when done.
c.DockerSpawner.remove = True

# We need to set the Notebook Directory
notebook_dir = '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir

# Need to tell where to mount the volumes.
c.DockerSpawner.volumes = { 'jupyterhub-user-{username}': notebook_dir }

Please note that djangodockerjupyterdemo_default is being created by docker-compose thanks to the name of the project directory being such. (I know this is not the best thing to do but right now I’m just hoping to have a bare minimal example working.)

Here is my docker-compose

version: "2"

services:
  database:
      image: "mysql:5.6"
      volumes:
      - ./data:/var/lib/mysql
      environment:
      - MYSQL_ROOT_PASSWORD=test123
      - MYSQL_DATABASE=oauthserver
      - MYSQL_USER=oauthadmin
      - MYSQL_PASSWORD=test123
  webapp:
    image: auth_server:latest
    volumes:
      - ./:/app
    links:
      - database:database
    environment:
      - PYTHONUNBUFFERED=1
      - ENV=DEV
      - DATABASE_HOST=database
      - DATABASE_USER=oauthadmin
      - DATABASE_DBNAME=oauthserver
      - DATABASE_PASSWORD=test123
    hostname: oauthserver.ddi.in
  jupyterhub:
    image: "jupyterhub:test"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:rw"
      - "./jupyterhub:/srv/jupyterhub"
    environment:
      - OAUTH2_AUTHORIZE_URL=http://oauthserver.ddi.in:8000/o/authorize
      - OAUTH2_TOKEN_URL=http://oauthserver.ddi.in:8000/o/token/
    hostname: jhtest.ddi.in
    links:
      - webapp:oauthserver.ddi.in

I use the https://hub.docker.com/r/defreitas/dns-proxy-server to be able to access the JupyterHub server by saying “http://jhtest.ddi.in:8000“.

Now, once the containers are up, here is what I can confirm.

  • “docker exec”ing into ‘webapp’ or ‘jupyterhub’ containers and then “wget”ing a file from some place on the Internet works.
  • “docker exec”ing into the spawned Jupyter notebook container and doing the same doesn’t. Same goes with trying to use ‘requests.get()’ from inside the notebook.

How can I make the spawned notebook access the outside world? It’s critical for my use case (and I’m sure a reasonable expectation).

PS: I notice there are hardly any examples covering OAuth JupyterHub setup with a custom Django application out there. I hope to publish my example publicly and hopefully it can constitute as a resource on the Jupyter Hub docs.

Source: StackOverflow