SwarmSpawner: A spawner for JupyterHub that uses Docker Swarm's services
Project description
# SwarmSpawner
**SwarmSpawner** enables [JupyterHub](https://github.com/jupyterhub/jupyterhub)
to spawn single user notebook servers in Docker Services.
More info about Docker Services [here](https://docs.docker.com/engine/reference/commandline/service_create/).
## Prerequisites
Python version 3.3 and above is required.
Clone the repo:
```bash
git clone https://github.com/cassinyio/SwarmSpawner
cd SwarmSpawner
```
Install dependencies:
```bash
pip install -r requirements.txt
```
## Installation
Install SwarmSpawner to the system:
```bash
python setup.py install
```
## Configuration
### SwarmSpawner
Docker Engine in Swarm mode and the related services work in a different way compared to Docker containers.
Tell JupyterHub to use SwarmSpawner by adding the following line to
your `jupyterhub_config.py`:
```python
c.JupyterHub.spawner_class = 'cassinyspawner.SwarmSpawner'
# This should be the name of the jupyterhub service
c.JupyterHub.hub_ip = 'jupyterhub'
```
There is the possibility to set parameters using `user_options`
```python
# To use user_options in service creation
c.SwarmSpawner.use_user_options = False
```
To control the creation of the services you have 2 ways, using _jupyterhub_config.py_ or _user_options_.
Remember that at the end you are just using the [Docker Engine API](https://docs.docker.com/engine/api/).
(https://docs.docker.com/engine/reference/commandline/service_create/#/specify-service-constraints---constraint)
### Use a configuration inside jupyterhub_config.py
You can define *container_spec*, *resource_spec* and _networks_ within jupyterhub_config.py.
#### [Container_spec](https://github.com/docker/docker-py/blob/master/docs/user_guides/swarm_services.md)
'command' depends from the image that you are using.
If you use one of the images from the Jupyter docker stack you need to specify a command: /usr/local/bin/start-singleuser.sh
If you are using a specific image, well it's up to you to specify the right command.
```python
c.SwarmSpawner.container_spec = {
# The command to be run inside the service
'command' : '/usr/local/bin/start-singleuser.sh', #(string or list)
'image' : 'YourImage',
'mounts' : mounts
}
```
##### Bind a Host dir
With mounts your are going to mount a local directory of the host inside the container.
<u>Remember that source should exist in the node where you are creating the service.</u>
notebook_dir = os.environ.get('DOCKER_NOTEBOOK_DIR') or '/home/jovyan/work'
c.SwarmSpawner.notebook_dir = notebook_dir
```python
mounts = [{'type' : 'bind',
'source' : 'MountPointOnTheHost',
'target' : 'MountPointInsideTheContainer',}]
```
##### Mount a named volume
With mounts your are going to mount a Docker Volume inside the container.
If the volume doesn't exist it will be created.
```python
mounts = [{'type' : 'volume',
'source' : 'NameOfTheVolume',
'target' : 'MountPointInsideTheContainer',}]
```
For this type of volume you can also specify something like this:
```python
mounts = [{'type' : 'volume',
'source' : 'jupyterhub-user-{username}',
'target' : 'MountPointInsideTheContainer',}]
```
username will be the hashed version of the username.
##### Mount an anonymous volume
__This kind of volume will be removed with the service__
```python
mounts = [{'type' : 'volume',
'target' : 'MountPointInsideTheContainer',}]
```
#### Resource_spec
You can also specify some resource for each service
```python
c.SwarmSpawner.resource_spec = {
'cpu_limit' : 1, # (int) – CPU limit in units of 10^9 CPU shares.
'mem_limit' : 512 * 1e6, # (int) – Memory limit in Bytes.
'cpu_reservation' : 1000, # (int) – CPU reservation in units of 10^9 CPU shares.
'mem_reservation' : 512 * 1e6, # (int) – Memory reservation in Bytes
}
```
#### Networks
You can also specify a network, remember to create the network before creating the service.
SwarmSpawner use the service name instead of the service ip as a consequence JupyterHub and servers should share the same overlay network (network across nodes).
```python
c.SwarmSpawner.networks = ["mynetwork"] #list of networks
```
### Using user_options
**user_options, if used, will overwrite jupyter_config.py for services.**
If you set 'c.SwarmSpawner.use_user_option = True' the spawner will use the dict passed through the form or as json body when using the Hub Api.
The spawner expect a dict with these keys:
```python
user_options = {
'container_spec' : {
'command' : '/usr/local/bin/start-singleuser.sh', #(string or list) command to be run in the image.
'image' : '', # name of the image
'mounts' : mounts, # Same as jupyterhub_config
'resource_spec' : {
'cpu_limit' : 1, # (int) – CPU limit in units of 10^9 CPU shares.
'mem_limit' : 512 * 1e6,# (int) – Memory limit in Bytes.
'cpu_reservation' : 1000, # (int) – CPU reservation in units of 10^9 CPU shares.
'mem_reservation' : 512 * 1e6, # (int) – Memory reservation in Bytes
},
'placement' : [], #list of constrains
'network' : [], #list of networks
'name' : '' # Name of service
```
### Services Prefix
Services using this format `{service_prefix}-{service_owner}-{service_suffix}`
You can change the service_prefix in this way:
Prefix of the service in Docker
```python
c.SwarmSpawner.service_prefix = "jupyterhub"
```
`service_owner` is the hexdigest() of the hashed `user.name`.
In case of multi sigle-server per user `service_suffix` is the name of the server, otherwise is always 1.
### Downloading images
Docker Engine in Swarm mode downloads images automatically from the repository.
Either the image is available on the remote repository or locally, if not you will get an error.
You can use all the docker images built for [JupyterHub](https://github.com/jupyter/docker-stacks).
## Contributing
If you would like to contribute to the project, please read our
[contributor documentation](http://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html)
and the [`CONTRIBUTING.md`](CONTRIBUTING.md).
For a **development install**, clone the [repository](https://github.com/jupyterhub/dockerspawner)
and then install from source:
```bash
git clone https://github.com/cassiny/CassinySpawner
cd CassinySpawner
pip3 install -r dev-requirements.txt -e .
```
## License
All code is licensed under the terms of the revised BSD license.
**SwarmSpawner** enables [JupyterHub](https://github.com/jupyterhub/jupyterhub)
to spawn single user notebook servers in Docker Services.
More info about Docker Services [here](https://docs.docker.com/engine/reference/commandline/service_create/).
## Prerequisites
Python version 3.3 and above is required.
Clone the repo:
```bash
git clone https://github.com/cassinyio/SwarmSpawner
cd SwarmSpawner
```
Install dependencies:
```bash
pip install -r requirements.txt
```
## Installation
Install SwarmSpawner to the system:
```bash
python setup.py install
```
## Configuration
### SwarmSpawner
Docker Engine in Swarm mode and the related services work in a different way compared to Docker containers.
Tell JupyterHub to use SwarmSpawner by adding the following line to
your `jupyterhub_config.py`:
```python
c.JupyterHub.spawner_class = 'cassinyspawner.SwarmSpawner'
# This should be the name of the jupyterhub service
c.JupyterHub.hub_ip = 'jupyterhub'
```
There is the possibility to set parameters using `user_options`
```python
# To use user_options in service creation
c.SwarmSpawner.use_user_options = False
```
To control the creation of the services you have 2 ways, using _jupyterhub_config.py_ or _user_options_.
Remember that at the end you are just using the [Docker Engine API](https://docs.docker.com/engine/api/).
(https://docs.docker.com/engine/reference/commandline/service_create/#/specify-service-constraints---constraint)
### Use a configuration inside jupyterhub_config.py
You can define *container_spec*, *resource_spec* and _networks_ within jupyterhub_config.py.
#### [Container_spec](https://github.com/docker/docker-py/blob/master/docs/user_guides/swarm_services.md)
'command' depends from the image that you are using.
If you use one of the images from the Jupyter docker stack you need to specify a command: /usr/local/bin/start-singleuser.sh
If you are using a specific image, well it's up to you to specify the right command.
```python
c.SwarmSpawner.container_spec = {
# The command to be run inside the service
'command' : '/usr/local/bin/start-singleuser.sh', #(string or list)
'image' : 'YourImage',
'mounts' : mounts
}
```
##### Bind a Host dir
With mounts your are going to mount a local directory of the host inside the container.
<u>Remember that source should exist in the node where you are creating the service.</u>
notebook_dir = os.environ.get('DOCKER_NOTEBOOK_DIR') or '/home/jovyan/work'
c.SwarmSpawner.notebook_dir = notebook_dir
```python
mounts = [{'type' : 'bind',
'source' : 'MountPointOnTheHost',
'target' : 'MountPointInsideTheContainer',}]
```
##### Mount a named volume
With mounts your are going to mount a Docker Volume inside the container.
If the volume doesn't exist it will be created.
```python
mounts = [{'type' : 'volume',
'source' : 'NameOfTheVolume',
'target' : 'MountPointInsideTheContainer',}]
```
For this type of volume you can also specify something like this:
```python
mounts = [{'type' : 'volume',
'source' : 'jupyterhub-user-{username}',
'target' : 'MountPointInsideTheContainer',}]
```
username will be the hashed version of the username.
##### Mount an anonymous volume
__This kind of volume will be removed with the service__
```python
mounts = [{'type' : 'volume',
'target' : 'MountPointInsideTheContainer',}]
```
#### Resource_spec
You can also specify some resource for each service
```python
c.SwarmSpawner.resource_spec = {
'cpu_limit' : 1, # (int) – CPU limit in units of 10^9 CPU shares.
'mem_limit' : 512 * 1e6, # (int) – Memory limit in Bytes.
'cpu_reservation' : 1000, # (int) – CPU reservation in units of 10^9 CPU shares.
'mem_reservation' : 512 * 1e6, # (int) – Memory reservation in Bytes
}
```
#### Networks
You can also specify a network, remember to create the network before creating the service.
SwarmSpawner use the service name instead of the service ip as a consequence JupyterHub and servers should share the same overlay network (network across nodes).
```python
c.SwarmSpawner.networks = ["mynetwork"] #list of networks
```
### Using user_options
**user_options, if used, will overwrite jupyter_config.py for services.**
If you set 'c.SwarmSpawner.use_user_option = True' the spawner will use the dict passed through the form or as json body when using the Hub Api.
The spawner expect a dict with these keys:
```python
user_options = {
'container_spec' : {
'command' : '/usr/local/bin/start-singleuser.sh', #(string or list) command to be run in the image.
'image' : '', # name of the image
'mounts' : mounts, # Same as jupyterhub_config
'resource_spec' : {
'cpu_limit' : 1, # (int) – CPU limit in units of 10^9 CPU shares.
'mem_limit' : 512 * 1e6,# (int) – Memory limit in Bytes.
'cpu_reservation' : 1000, # (int) – CPU reservation in units of 10^9 CPU shares.
'mem_reservation' : 512 * 1e6, # (int) – Memory reservation in Bytes
},
'placement' : [], #list of constrains
'network' : [], #list of networks
'name' : '' # Name of service
```
### Services Prefix
Services using this format `{service_prefix}-{service_owner}-{service_suffix}`
You can change the service_prefix in this way:
Prefix of the service in Docker
```python
c.SwarmSpawner.service_prefix = "jupyterhub"
```
`service_owner` is the hexdigest() of the hashed `user.name`.
In case of multi sigle-server per user `service_suffix` is the name of the server, otherwise is always 1.
### Downloading images
Docker Engine in Swarm mode downloads images automatically from the repository.
Either the image is available on the remote repository or locally, if not you will get an error.
You can use all the docker images built for [JupyterHub](https://github.com/jupyter/docker-stacks).
## Contributing
If you would like to contribute to the project, please read our
[contributor documentation](http://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html)
and the [`CONTRIBUTING.md`](CONTRIBUTING.md).
For a **development install**, clone the [repository](https://github.com/jupyterhub/dockerspawner)
and then install from source:
```bash
git clone https://github.com/cassiny/CassinySpawner
cd CassinySpawner
pip3 install -r dev-requirements.txt -e .
```
## License
All code is licensed under the terms of the revised BSD license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
No source distribution files available for this release.See tutorial on generating distribution archives.
Built Distribution
File details
Details for the file swarmspawner-0.0.3-py2.py3-none-any.whl
.
File metadata
- Download URL: swarmspawner-0.0.3-py2.py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | c4c122762bfa5fa390679d68664e9f6eee0bba5e82235017061ae33cc1ea9509 |
|
MD5 | 5eadeb417dd52cd8780e99e272ffee1f |
|
BLAKE2b-256 | 334b9c92eb9efc5f38f56ce4515cf9176525f9ff574c972e6d9740e0b8a8fe37 |