Skip to content

Instantly share code, notes, and snippets.

@parente
Last active November 28, 2022 19:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save parente/bd0b71f15ba0b97139e5 to your computer and use it in GitHub Desktop.
Save parente/bd0b71f15ba0b97139e5 to your computer and use it in GitHub Desktop.
Jupyter Notebooks as OpenWhisk Actions
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {},
"cell_type": "markdown",
"source": "# Jupyter Notebooks as OpenWhisk Actions\n\n> OpenWhisk on IBM Bluemix: Post your code. We host it. We scale it up. Pay only for what you use.\n\n[OpenWhisk on IBM Bluemix](https://new-console.ng.bluemix.net/openwhisk/) supports Dockerized actions. [Jupyter Kernel Gateway](https://github.com/jupyter/kernel_gateway) can turn annotated Jupyter notebooks into microservices that run in Docker.\n\nLet's put them together and create [Jupyter notebook-powered](https://jupyter.org) Whisk actions! &#x1F388;\n\n<p><a href=\"https://asciinema.org/a/1wkyfecyj2qa4t9gm4bank61y\" target=\"_blank\"><img src=\"https://asciinema.org/a/1wkyfecyj2qa4t9gm4bank61y.png\" width=\"605px\"/></a></p>"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Why?!\n\n1. Build your data analyses in [notebooks](https://jupyter.org).\n2. Deploy them as [OpenWhisk actions](https://new-console.ng.bluemix.net/docs/openwhisk/openwhisk_actions.html).\n3. [Trigger](https://new-console.ng.bluemix.net/docs/openwhisk/openwhisk_triggers_rules.html) them on-demand in your solution.\n4. [Package](https://new-console.ng.bluemix.net/docs/openwhisk/openwhisk_packages.html) them for reuse by others."
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Hello World Action\n\nHere's a dirt simple hello world web API. It uses annotations supported by the [Jupyter Kernel Gateway](http://jupyter-kernel-gateway.readthedocs.org/en/latest/http-mode.html#notebook-http-mode) to define the API endpoints. Here it is written in Python. It could be written in [any language supported by Jupyter](https://github.com/ipython/ipython/wiki/IPython-kernels-for-other-languages). "
},
{
"metadata": {
"trusted": true,
"collapsed": true
},
"cell_type": "code",
"source": "import json",
"execution_count": 43,
"outputs": []
},
{
"metadata": {
"trusted": true,
"collapsed": true
},
"cell_type": "code",
"source": "def tojson(data):\n '''Shorten the code to respond a little bit.'''\n print(json.dumps(data))",
"execution_count": 50,
"outputs": []
},
{
"metadata": {
"trusted": true,
"collapsed": false
},
"cell_type": "code",
"source": "REQUEST = json.dumps({\n 'body': {},\n 'headers': {}\n})",
"execution_count": 56,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "OpenWhisk requires an `init` endpoint."
},
{
"metadata": {
"trusted": true,
"collapsed": false
},
"cell_type": "code",
"source": "# POST /init\ntojson({})",
"execution_count": 57,
"outputs": [
{
"output_type": "stream",
"text": "{}\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "OpenWhisk will `POST` to the `run` endpoint on every action invocation."
},
{
"metadata": {
"trusted": true,
"collapsed": false
},
"cell_type": "code",
"source": "# POST /run\nreq = json.loads(REQUEST)\nname = req.get('body', {}).get('value', {}).get('name', 'world')\ntojson(data = {\n 'msg': 'Hello {} from a Jupyter Notebook!'.format(name)\n})",
"execution_count": 62,
"outputs": [
{
"output_type": "stream",
"text": "{\"msg\": \"Hello world from a Jupyter Notebook!\"}\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Deploy It\n\nPublish this notebook to the web somewhere. For simplicity, I've made this one a GitHub gist: https://gist.github.com/parente/bd0b71f15ba0b97139e5.\n\nCreate a Dockerfile:\n\n```\n# Use a barebones image from jupyter/docker-stacks for this\n# simple example. Replace with another docker-stacks image\n# if the notebook has more complex dependencies.\nFROM jupyter/minimal-kernel\n\n# Put the jupyter kernel gateway into microservice mode\nENV KG_API notebook-http\n# Point to our gist as the API definition.\nENV KG_SEED_URI https://gist.githubusercontent.com/parente/bd0b71f15ba0b97139e5/raw/nbwhisk.ipynb\n# Listen on the port OpenWhisk wants.\nENV KG_PORT 8080\nEXPOSE 8080\n```\n\nBuild and push the image:\n\n```\ndocker build --rm -t parente/nbwhisk \ndocker push parente/nbwhisk\n```\n\nCreate the whisk action:\n\n```\nwsk action create --docker nbwhisk parente/nbwhisk\n```\n\nInvoke it:\n\n```\nwsk action invoke --blocking nbwhisk\n```\n\nUpdate the notebook and republish it to the web. Then update the action:\n\n```\nwsk action update --docker nbwhisk parente/nbwhisk\n```\n\nThere's no need to rebuild / repush the Docker image in this example because the notebook lives on the open web. If it resided directly in the Docker image, a rebuild/repush would be in order."
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Go Further\n\n* Chain multiple notebooks into aggregate actions.\n* Invoke your actions from other applications using the [OpenWhisk REST API](https://new-console.ng.bluemix.net/apidocs/98#introduction).\n* Combine notebook actions with [other supported service actions](https://new-console.ng.bluemix.net/docs/openwhisk/openwhisk_catalog.html).\n\nMore intriguing demo coming soon ...? &#x1F648;&#x1F649;&#x1F64A;"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "*Copyright (c) IBM Corp. 2016 under the MIT License*"
}
],
"metadata": {
"kernelspec": {
"name": "python3",
"display_name": "Python 3",
"language": "python"
},
"language_info": {
"mimetype": "text/x-python",
"nbconvert_exporter": "python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"pygments_lexer": "ipython3",
"name": "python",
"version": "3.5.1"
},
"gist_id": "bd0b71f15ba0b97139e5"
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment