Prerequisites | Installation | Configuration | Building the Docker images | Contributing | License | Getting help


DockerSpawner enables JupyterHub to spawn single user notebook servers in Docker containers.


Python version 3.3 and above is required.

Clone the repo:

    git clone
    cd dockerspawner

Install dependencies:

    pip install -r requirements.txt


Install dockerspawner to the system:

    python install


Choose a spawner

Two basic types of spawners are available for dockerspawner:

  • DockerSpawner: useful if you would like to spawn single user notebook servers on the fly. It will take an authenticated user and spawn a notebook server in a Docker container for the user.
  • SystemUserSpawner: useful if you would like to spawn single user notebook servers that correspond to the system’s users.

In most cases, we recommend using DockerSpawner. Use cases where you may wish to use SystemUserSpawner are:

  • You are using docker just for environment management, but are running on a system where the users already have accounts and files they should be able to access from within the container. For example, you wish to use the system users and user home directories that already exist on a system.
  • You are using an external service, such as nbgrader, that relies on distinct unix user ownership and permissions.

If neither of those cases applies, DockerSpawner is probably the right choice.


Tell JupyterHub to use DockerSpawner by adding the following line to your

    c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'

There is a complete example in examples/oauth for using GitHub OAuth to authenticate users, and spawn containers with docker.


If you want to spawn notebook servers for users that correspond to system users, you can use the SystemUserSpawner instead. Add the following to your

    c.JupyterHub.spawner_class = 'dockerspawner.SystemUserSpawner'

The SystemUserSpawner will also need to know where the user home directories are on the host. By default, it expects them to be in /home/<username>, but if you want to change this, you’ll need to further modify the For example, the following will look for a user’s home directory on the host system at /volumes/user/<username>:

    c.SystemUserSpawner.host_homedir_format_string = '/volumes/user/{username}'

For a full example of how SystemUserSpawner is used, see the compmodels-jupyterhub repository (this additionally runs the JupyterHub server within a docker container, and authenticates users using GitHub OAuth).

Using Docker Swarm

Both DockerSpawner and SystemUserSpawner are compatible with Docker Swarm when multiple system nodes will be used in a cluster for JupyterHub. Simply add to your file as the container_ip:

c.DockerSpawner.container_ip = ""

This will configure DockerSpawner and SystemUserSpawner to get the container IP address and port number using the docker port command.

Data persistence and DockerSpawner

With DockerSpawner, the user’s home directory is not persistent by default, so some configuration is required to do so unless the directory is to be used with temporary or demonstration JupyterHub deployments.

The simplest version of persistence to the host filesystem is to isolate users in the filesystem, but leave everything owned by the same ‘actual’ user with DockerSpawner. That is, using docker mounts to isolate user files, not ownership or permissions on the host.

Volume mapping for DockerSpawner in is required configuration for persistence. To map volumes from the host file/directory to the container (referred to as guest) file/directory mount point, set the c.DockerSpawner.volumes to specify the guest mount point (bind) for the volume.

If you use {username} in either the host or guest file/directory path, username substitution will be done and {username} will be replaced with the current user’s name.

(Note: The jupyter/docker-stacks notebook images run the Notebook server as user jovyan and set the user’s notebook directory to /home/jovyan/work.)

# Explicitly set notebook directory because we'll be mounting a host volume to
# it.  Most jupyter/docker-stacks *-notebook images run the Notebook server as
# user `jovyan`, and set the notebook directory to `/home/jovyan/work`.
# We follow the same convention.
notebook_dir = os.environ.get('DOCKER_NOTEBOOK_DIR') or '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir

# Mount the real user's Docker volume on the host to the notebook user's
# notebook directory in the container
c.DockerSpawner.volumes = { 'jupyterhub-user-{username}': notebook_dir }

The jupyterhub-deploy-docker repo contains a reference deployment that persists the notebook directory; see its for an example configuration.

See Docker documentation on data volumes for more information on data persistence.

Building the Docker images

Single user notebook server

Build the jupyterhub/singleuser container with:

    docker build -t jupyterhub/singleuser singleuser

You may also use docker pull jupyterhub/singleuser to download the container from Docker Hub.

System user notebook server

This is used with SystemUserSpawner.

Build the jupyterhub/systemuser container with:

    docker build -t jupyterhub/systemuser systemuser

You may also use docker pull jupyterhub/systemuser to download the containter from Docker Hub.


If you would like to contribute to the project, please read our contributor documentation and the

For a development install, clone the repository and then install from source:

git clone
cd dockerspawner
pip3 install -r dev-requirements.txt -e .


We use a shared copyright model that enables all contributors to maintain the copyright on their contributions.

All code is licensed under the terms of the revised BSD license.

Getting help

We encourage you to ask questions on the mailing list, and you may participate in development discussions or get live help on Gitter.