This is an automated email from the ASF dual-hosted git repository.

jamesthomas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git


The following commit(s) were added to refs/heads/master by this push:
     new 5a40820  Updating Node.js and Docker docs. (#4451)
5a40820 is described below

commit 5a408201a1afac72785d96d10ecbf3e114783c5e
Author: James Thomas <jthomas...@gmail.com>
AuthorDate: Tue Apr 23 11:41:43 2019 +0100

    Updating Node.js and Docker docs. (#4451)
    
    * Updating Node.js and Docker docs.
    
    Adding common use-case instructions based on community feedback.
    
    * Fixing scancode issues
---
 docs/actions-docker.md | 435 +++++++++++++++++++++++++++++++++----------------
 docs/actions-nodejs.md | 317 ++++++++++++++++++++++++-----------
 2 files changed, 515 insertions(+), 237 deletions(-)

diff --git a/docs/actions-docker.md b/docs/actions-docker.md
index 84ce543..5d53a1c 100644
--- a/docs/actions-docker.md
+++ b/docs/actions-docker.md
@@ -19,149 +19,298 @@
 
 ## Creating and invoking Docker actions
 
-With OpenWhisk Docker actions, you can write your actions in any language, 
bundle larger
-or complex dependencies, and tailor the runtime environment to suite your 
needs.
-
-- As a prerequisite, you must have a Docker Hub account.
-  To set up a free Docker ID and account, go to [Docker 
Hub](https://hub.docker.com).
-- The easiest way to get started with a Docker action is to use the OpenWhisk 
Docker skeleton.
-  - You can install the skeleton with the `wsk sdk install docker` CLI command.
-  - This is a a Docker image based on 
[python:3.6.1-alpine](https://hub.docker.com/r/library/python).
-  - The skeleton requires an entry point located at `/action/exec` inside the 
container.
-    This may be an executable script or binary compatible with this 
distribution.
-  - The executable receives the input arguments via a single command-line 
argument string
-    which can be deserialized as a `JSON` object.
-    It must return a result via `stdout` as a single-line string of serialized 
`JSON`.
-  - You may include any compilation steps or dependencies by modifying the 
`Dockerfile`
-    included in the `dockerSkeleton`.
-
-The instructions that follow show you how to use the OpenWhisk Docker skeleton.
-
-1. Install the Docker skeleton.
-
-  ```
-  wsk sdk install docker
-  ```
-  ```
-  The Docker skeleton is now installed at the current directory.
-  ```
-
-  ```
-  $ ls dockerSkeleton/
-  ```
-  ```
-  Dockerfile      README.md       buildAndPush.sh example.c
-  ```
-
-  The skeleton is a Docker container template where you can inject your code 
in the form of custom binaries.
-
-2. Create the executable. The Docker skeleton includes a C program that you 
can use as an example.
-
-  ```
-  cat dockerSkeleton/example.c
-  ```
-  ```c
-  #include <stdio.h>
-  int main(int argc, char *argv[]) {
-      printf("This is an example log message from an arbitrary C program!\n");
-      printf("{ \"msg\": \"Hello from arbitrary C program!\", \"args\": %s }",
-             (argc == 1) ? "undefined" : argv[1]);
-  }
-  ```
-
-  You can modify this file as needed, or, add additional code and dependencies 
to the Docker image.
-  In case of the latter, you may need to tweak the `Dockerfile` as necessary 
to build your executable.
-  The binary must be located inside the container at `/action/exec`.
-
-  The executable receives a single argument from the command line. It is a 
string serialization of the JSON
-  object representing the arguments to the action. The program may log to 
`stdout` or `stderr`.
-  By convention, the last line of output _must_ be a stringified JSON object 
which represents the result of
-  the action.
-
-3. Build the Docker image and upload it using a supplied script.
-  You must first run `docker login` to authenticate, and then run the script 
with a chosen image name.
-
-  ```
-  docker login -u janesmith -p janes_password
-  ```
-  ```
-  cd dockerSkeleton
-  ```
-  ```
-  ./buildAndPush.sh janesmith/blackboxdemo
-  ```
-
-  Notice that part of the example.c file is compiled as part of the Docker 
image build process,
-  so you do not need C compiled on your machine.
-  In fact, unless you are compiling the binary on a compatible host machine, 
it may not run inside
-  the container since formats will not match.
-
-  Your Docker container may now be used as an OpenWhisk action.
-
-  ```
-  wsk action create example --docker janesmith/blackboxdemo
-  ```
-
-  Notice the use of `--docker` when creating an action. Currently all Docker 
images are assumed
-  to be hosted on Docker Hub.
-
-  *Note:* It is considered best-practice for production images to be versioned 
via docker image tags. The absence of a tag will be treated the same as using a 
"latest" tag, which will result in a pull from the registry when creating new 
containers. Pulling an image may fail due to a network interruption or Docker 
Hub outage. For tagged images however, the system will gracefully recover from 
a failed pull by using the image that is already locally available, making it 
much more resilient  [...]
-
-  The "latest" tag should therefore only be used for rapid prototyping where 
guaranteeing the latest code state is more important than runtime stability at 
scale.
-
-  Please also note that "latest" doesn't mean newest tag, but rather "latest" 
is an alias for any image built without an explicit tag.
-
-## Invoking a Docker action
-
-Docker actions are invoked as [any other OpenWhisk 
action](actions.md#the-basics).
-
-  ```
-  wsk action invoke --result example --param payload Rey
-  ```
-  ```json
-  {
-      "args": {
-          "payload": "Rey"
-      },
-      "msg": "Hello from arbitrary C program!"
-  }
-  ```
-
-## Updating a Docker action
-
-To update the Docker action, run buildAndPush.sh again _and_ update your 
action.
-This will upload the latest image to Docker Hub and force the system to create 
a new container based on the image.
-If you do not update the action, then the image is pulled when there are no 
warm containers available for your action.
-A warm container will continue using a previous version of your Docker image,
-and any new invocations of the action will continue to use that image unless 
you run `wsk action update`.
-This will indicate to the system that for new invocations it should execute a 
docker pull to get your new Docker image.
-
-  ```
-  ./buildAndPush.sh janesmith/blackboxdemo
-  ```
-  ```
-  wsk action update example --docker janesmith/blackboxdemo
-  ```
-
-**Note:** As noted above, only images with the tag "latest" or no tag will 
guarantee to be pulled again, even after updating the action. Any other tag 
might fall back to use the old image for stability reasons.
-
-To force an updated image after an action update, consider using versioned 
tags on the image.
+Apache OpenWhisk supports using custom Docker images as the action runtime. 
Custom runtimes images can either have the action source files built-in or 
injected dynamically by the platform during initialisation.
+
+Building custom runtime images is a common solution to the issue of having 
external application dependencies too large to deploy, due to the action size 
limit (48MB), e.g. machine learning libraries.
+
+### Usage
+
+The [Apache OpenWhisk CLI](https://github.com/apache/incubator-openwhisk-cli) 
has a `--docker` configuration parameter to set a custom runtime for an action.
+
+```
+wsk action create <ACTION_NAME> --docker <IMAGE> source.js
+```
+
+*`<IMAGE>` must be an image name for a public Docker image on [Docker 
Hub](https://hub.docker.com/search?q=&type=image).*
+
+The `--docker` flag can also be used without providing additional source or 
archive files for an action.
+
+```
+wsk action create <ACTION_NAME> --docker <IMAGE>
+```
+
+In this scenario, action source code will not be injected into the runtime 
during cold-start initialisation. The runtime container must handle the 
platform invocation requests directly.
+
+### Restrictions
+
+- Custom runtime images must implement the [Action 
interface](https://github.com/apache/incubator-openwhisk/blob/master/docs/actions-new.md#runtime-general-requirements).
 This is the [protocol used by the 
platform](https://github.com/apache/incubator-openwhisk/blob/master/docs/actions-new.md#action-interface)
 to pass invocation requests to the runtime containers. Containers are expected 
to expose a HTTP server (running on port 8080) with `/init` and `/run` 
endpoints.
+- Custom runtime images must be available on [Docker 
Hub](https://hub.docker.com/search?q=&type=image). Docker Hub is the only 
container registry currently supported. This means all custom runtime images 
will need to be publicly available.
+- Custom runtime images will be pulled from Docker Hub into the local platform 
registry upon the first invocation. This can lead to longer cold-start times on 
the first invocation with a new or updated image. Once images have been pulled 
down, they are cached locally.
+
+### Image Refresh Behaviour
+
+Custom runtimes images should be versioned using explicit [image 
tags](https://docs.docker.com/engine/reference/commandline/tag/) where possible.
+
+When an image identifier has the `latest` tag (or has no explicit tag), 
creating new runtime containers from a custom image will always result in an 
image refresh check against the registry. Pulling an image may fail due to a 
network interruption or Docker Hub outage. Explicitly tagged images allow the 
system to gracefully recover by using locally cached images, making it much 
more resilient against external issues.
+
+The "latest" tag should only be used for rapid prototyping, where guaranteeing 
the latest code state is more important than runtime stability at scale.
+
+### Existing Runtime Images
+
+Apache OpenWhisk publishes all the [existing runtime 
images](https://hub.docker.com/u/openwhisk) on Docker Hub. This makes it simple 
to extend an existing runtimes with additional libraries or native 
dependencies. Public runtimes images can be used as base images in new runtime 
images.
+
+Here are some of the more common runtime images...
+
+- `openwhisk/action-nodejs-v10` - [Node.js 
10](https://hub.docker.com/r/openwhisk/action-nodejs-v10) 
([Source](https://github.com/apache/incubator-openwhisk-runtime-nodejs/blob/master/core/nodejs10Action/Dockerfile))
+- `openwhisk/python3action` - [Python 
3](https://hub.docker.com/r/openwhisk/python3action) 
([Source](https://github.com/apache/incubator-openwhisk-runtime-python/blob/master/core/pythonAction/Dockerfile))
+- `openwhisk/java8action` - [Java 
8](https://hub.docker.com/r/openwhisk/java8action) 
([Source](https://github.com/apache/incubator-openwhisk-runtime-java/blob/master/core/java8/Dockerfile))
+- `openwhisk/action-swift-v4.2` - [Swift 
4.2](https://hub.docker.com/r/openwhisk/action-swift-v4.2) 
([Source](https://github.com/apache/incubator-openwhisk-runtime-swift/blob/master/core/swift42Action/Dockerfile))
+- `openwhisk/action-php-v7.3` - [PHP 
7.3](https://hub.docker.com/r/openwhisk/action-php-v7.3) 
([Source](https://github.com/apache/incubator-openwhisk-runtime-php/blob/master/core/php7.3Action/Dockerfile))
+- `openwhisk/action-ruby-v2.5` - [Ruby 
2.5](https://hub.docker.com/r/openwhisk/action-ruby-v2.5) 
([Source](https://github.com/apache/incubator-openwhisk-runtime-ruby/blob/master/core/ruby2.5Action/Dockerfile))
+
+## Extending Existing Runtimes
+
+If you want to use extra libraries in an action that can't be deployed (due to 
the action size limit), building a custom runtime with a project image runtime 
base image is an easy way to handle this.
+
+By using an existing language runtime image as the base image, the container 
will already be set up to handle platform invocation requests for that 
language. This means the image build file only needs to contain commands to 
install those extra libraries or dependencies
+
+Here are examples for Node.js and Python using this approach to provide large 
libraries in the runtime.
+
+### Node.js
+
+[Tensorflow.js](https://www.tensorflow.org/js/) is a JavaScript implementation 
of [TensorFlow](https://www.tensorflow.org/), the open-source Machine Learning 
library from Google. This project also comes with a [Node.js backend 
driver](https://github.com/tensorflow/tfjs-node) to run the project on CPU or 
GPU devices in the Node.js runtime.
+
+Both the core library and CPU backend driver for Node.js (`tfjs` and 
`tfjs-node`) can be installed as normal NPM packages. Unfortunately, it is not 
possible to deploy these libraries in a zip file to the Node.js runtime in 
Apache OpenWhisk due to the size of the library and its dependencies. The 
`tfjs-node` library has a native dependency which is over 170MB.
+
+Instead, we can build a custom runtime which extends the project's Node.js 
runtime image and runs `npm install` during the container build process. These 
libraries will then be pre-installed into the runtime and can be excluded from 
the deployment archive.
+
+- Create a `Dockerfile` with the following contents:
+
+```
+FROM openwhisk/action-nodejs-v10:latest
+
+RUN npm install @tensorflow/tfjs-node
+```
+
+- Build the Docker image.
+
+```
+docker build -t action-nodejs-v10:tf-js .
+```
+
+- Tag the Docker image with your Docker Hub username.
+
+```
+docker tag action-nodejs-v10:tf-js <USER_NAME>/action-nodejs-v10:tf-js
+```
+
+- Push the Docker image to Docker Hub.
+
+```
+docker push <USER_NAME>/action-nodejs-v10:tf-js
+```
+
+- Create a new Apache OpenWhisk action with the following source code:
+
+```javascript
+const tf = require('@tensorflow/tfjs-node')
+
+const main = () => {
+  return { tf: tf.version }
+}
+```
+
+```
+wsk action create tfjs --docker <USER_NAME>/action-nodejs-v10:tf-js action.js
+```
+
+- Invoking the action should return the TensorFlow.js libraries versions 
available in the runtime.
+
+```
+wsk action invoke tfjs --result
+```
+
+```
+{
+    "tf": {
+        "tfjs": "1.0.4",
+        "tfjs-converter": "1.0.4",
+        "tfjs-core": "1.0.4",
+        "tfjs-data": "1.0.4",
+        "tfjs-layers": "1.0.4",
+        "tfjs-node": "1.0.3"
+    }
+}
+```
+
+### Python
+
+Python is a popular language for machine learning and data science due to 
availability of libraries like [numpy](http://www.numpy.org/).
+
+Python libraries can be [imported into the Python 
runtime](https://github.com/apache/incubator-openwhisk/blob/master/docs/actions-python.md#packaging-python-actions-with-a-virtual-environment-in-zip-files)
 in Apache OpenWhisk by including a `virtualenv` folder in the deployment 
archive. This approach does not work when the deployment archive would be 
larger than the action size limit (48MB).
+
+Instead, we can build a custom runtime which extends the project's Python 
runtime image and runs `pip install` during the container build process. These 
libraries will then be pre-installed into the runtime and can be excluded from 
the deployment archive.
+
+- Create a `Dockerfile` with the following contents:
+
+```
+FROM openwhisk/python3action:latest
+
+RUN apk add --update py-pip
+RUN pip install numpy
+```
+
+- Build the Docker image.
+
+```
+docker build -t python3action:ml-libs .
+```
+
+- Tag the Docker image with your Docker Hub username.
+
+```
+docker tag python3action:ml-libs <USER_NAME>/python3action:ml-libs
+```
+
+- Push the Docker image to Docker Hub.
+
+```
+docker push <USER_NAME>/python3action:ml-libs
+```
+
+- Create a new Apache OpenWhisk action with the following source code:
+
+```python
+import numpy
+
+def main(params):
+    return {
+        "numpy": numpy.__version__
+    }
+```
+
+```
+wsk action create ml-libs --docker <USER_NAME>/python3action:ml-libs action.py
+```
+
+- Invoking the action should return the TensorFlow.js library versions 
available in the runtime.
+
+```
+wsk action invoke ml-libs --result
+```
+
+```
+{
+    "numpy": "1.16.2"
+}
+```
 
 ## Creating native actions
 
-Docker actions accept initialization data via a (zip) file, similar to other 
actions kinds.
-For example, the tutorial above created a binary executable inside the 
container located at `/action/exec`.
-If you copy this file to your local file system and zip it into `exec.zip` 
then you can use the following
-commands to create a docker action which receives the executable as 
initialization data.
-
-  ```bash
-  wsk action create example exec.zip --native
-  ```
-  which is equivalent to the following command.
-  ```bash
-  wsk action create example exec.zip --docker openwhisk/dockerskeleton
-  ```
-
-Using `--native`, you can see that any executable may be run as an OpenWhisk 
action.
-This includes `bash` scripts, or cross compiled binaries. For the latter, the 
constraint
-is that the binary must be compatible with the `openwhisk/dockerskeleton` 
image.
+Docker support can also be used to run any executable file (from static 
binaries to shell scripts) on the platform. Executable files need to use the 
`openwhisk/dockerskeleton` [runtime 
image](https://github.com/apache/incubator-openwhisk-runtime-docker). Native 
actions can be created using the `--native` CLI flag, rather than explicitly 
specifying `dockerskeleton` as the runtime image name.
+
+### Usage
+
+```
+wsk action create my-action --native source.sh
+wsk action create my-action --native archive.zip
+```
+
+Executables can either be text or binary files. Text-based executable files 
(e.g. shell scripts) are passed directly as the action source files. Binary 
files (e.g. C programs) must be named `exec` and packaged into a zip archive.
+
+Native action source files must be executable within the  
`openwhisk/dockerskeleton` [runtime 
image](https://github.com/apache/incubator-openwhisk-runtime-docker). This 
means being compiled for the correct platform architecture, linking to the 
correct dynamic libraries  and using pre-installed external dependencies.
+
+When an invocation request is received by the runtime container, the native 
action file will be executed until the process exits. Action invocation 
parameters will be passed as a JSON string to `stdin`.
+
+When the process ends, the last line of text output to `stdout` will be parsed 
as the action result. This must contain a text string with a JSON object. All 
other text lines written to `stdout` will be treated as logging output and 
returned into the response logs for the activation.
+
+### Example (Shell Script)
+
+- Create a shell script called `script.sh` with the following contents.
+
+```
+#!/bin/bash
+read ARGS
+NAME=`echo "$ARGS" | jq -r '."name"'`
+DATE=`date`
+echo "{ \"message\": \"Hello $NAME! It is $DATE.\" }"
+```
+
+- Create an action from this shell script.
+
+```
+ wsk action create bash script.sh --native
+```
+
+- Invoke the action with the `name` parameter.
+
+```
+wsk action invoke bash --result --param name James
+```
+
+```
+{
+    "message": "Hello James! It is Thu Apr 18 15:24:23 UTC 2019."
+}
+```
+
+### Example (Static C Binary)
+
+- Create a C source file called `main.c` with the following contents:
+
+```c
+#include <stdio.h>
+int main(int argc, char *argv[]) {
+    printf("This is an example log message from an arbitrary C program!\n");
+    printf("{ \"msg\": \"Hello from arbitrary C program!\", \"args\": %s }",
+           (argc == 1) ? "undefined" : argv[1]);
+}
+```
+
+- Create a shell script (`build.sh`) with the following contents:
+
+```
+#!/bin/bash
+apk add gcc libc-dev
+
+gcc main.c -o exec
+```
+
+- Make the build script executable.
+
+```
+chmod 755 build.sh
+```
+
+- Compile the C binary using the `dockerskeleton` image and the build script.
+
+```
+docker run -it -v $PWD:/action/ -w /action/ openwhisk/dockerskeleton ./build.sh
+```
+
+- Add the binary to a zip file.
+
+```
+zip -r action.zip exec
+```
+
+- Create an action from the zip file containing the binary.
+
+```
+ wsk action create c-binary action.zip --native
+```
+
+- Invoke the action with the `name` parameter.
+
+```
+wsk action invoke c-binary --result --param name James
+```
+
+```
+{
+    "args": {
+        "name": "James"
+    },
+    "msg": "Hello from arbitrary C program!"
+}
+```
diff --git a/docs/actions-nodejs.md b/docs/actions-nodejs.md
index ff6434e..9c76149 100644
--- a/docs/actions-nodejs.md
+++ b/docs/actions-nodejs.md
@@ -104,7 +104,7 @@ Datetime            Activation ID                    Kind   
   Start Duration
       "end":   1552762005048,
       ...
   }
-  ```
+ ```
 
   Comparing the `start` and `end` time stamps in the activation record, you 
can see that this activation took slightly over two seconds to complete.
 
@@ -166,11 +166,17 @@ This example invokes a Yahoo Weather service to get the 
current conditions at a
 
 This example also passed a parameter to the action by using the `--param` flag 
and a value that can be changed each time the action is invoked. Find out more 
about parameters in the [Working with parameters](./parameters.md) section.
 
-## Packaging an action as a Node.js module
+## Packaging actions as Node.js modules with NPM libraries
+
+Instead of writing all your action code in a single JavaScript source file, 
actions can be deployed from a zip file containing a [Node.js 
module](https://nodejs.org/docs/latest-v10.x/api/modules.html#modules_modules).
+
+Archive zip files are extracted into the runtime environment and dynamically 
imported using `require()` during initialisation. **Actions packaged as a zip 
file MUST contain a valid `package.json` with a `main` field used to denote the 
[module index 
file](https://nodejs.org/docs/latest-v10.x/api/modules.html#modules_folders_as_modules)
 to return.**
 
-As an alternative to writing all your action code in a single JavaScript 
source file, you can write an action as a `npm` package. Consider as an example 
a directory with the following files:
+Including a `node_modules` folder in the zip file means external NPM libraries 
can be used on the platform.
 
-First, `package.json`:
+### Simple Example
+
+- Create the following `package.json` file:
 
 ```json
 {
@@ -182,7 +188,7 @@ First, `package.json`:
 }
 ```
 
-Then, `index.js`:
+- Create the following `index.js` file:
 
 ```javascript
 function myAction(args) {
@@ -194,132 +200,261 @@ function myAction(args) {
 exports.main = myAction;
 ```
 
-Note that the action is exposed through `exports.main`; the action handler 
itself can have any name, as long as it conforms to the usual signature of 
accepting an object and returning an object (or a `Promise` of an object). Per 
Node.js convention, you must either name this file `index.js` or specify the 
file name you prefer as the `main` property in package.json.
+Functions are exported from a module by setting properties on the `exports` 
object. The `--main` property on the action can be used to configure the module 
function invoked by the platform (this defaults to `main`).
 
-To create an OpenWhisk action from this package:
+- Install module dependencies using NPM.
 
-1. Install first all dependencies locally
+```
+npm install
+```
 
-  ```
-  $ npm install
-  ```
+- Create a `.zip` archive containing all files (including all dependencies).
 
-2. Create a `.zip` archive containing all files (including all dependencies):
+```
+zip -r action.zip *
+```
 
-  ```
-  $ zip -r action.zip *
-  ```
+> Please note: Using the Windows Explorer action for creating the zip file 
will result in an incorrect structure. OpenWhisk zip actions must have 
`package.json` at the root of the zip, while Windows Explorer will put it 
inside a nested folder. The safest option is to use the command line `zip` 
command as shown above.
 
-  > Please note: Using the Windows Explorer action for creating the zip file 
will result in an incorrect structure. OpenWhisk zip actions must have 
`package.json` at the root of the zip, while Windows Explorer will put it 
inside a nested folder. The safest option is to use the command line `zip` 
command as shown above.
+- Create the action from the zip file.
 
-3. Create the action:
+```
+wsk action create packageAction --kind nodejs:10 action.zip
+```
 
-  ```
-  wsk action create packageAction --kind nodejs:10 action.zip
-  ```
+When creating an action from a `.zip` archive with the CLI tool, you must 
explicitly provide a value for the `--kind` flag by using `nodejs:10`, 
`nodejs:8` or `nodejs:6`.
+
+- Invoke the action as normal.
+
+```
+wsk action invoke --result packageAction --param lines "[\"and now\", \"for 
something completely\", \"different\" ]"
+```
+```json
+{
+    "padded": [
+        ".......................and now",
+        "......for something completely",
+        ".....................different"
+    ]
+}
+```
 
-  When creating an action from a `.zip` archive with the CLI tool, you must 
explicitly provide a value for the `--kind` flag by using `nodejs:10`, 
`nodejs:8` or `nodejs:6`.
+### Handling NPM Libraries with Native Dependencies
 
-4. You can invoke the action like any other:
+Node.js libraries can import native dependencies needed by the modules. These 
native dependencies are compiled upon installation to ensure they work in the 
local runtime. Native dependencies for NPM libraries must be compiled for the 
correct platform architecture to work in Apache OpenWhisk.
 
-  ```
-  wsk action invoke --result packageAction --param lines "[\"and now\", \"for 
something completely\", \"different\" ]"
-  ```
-  ```json
-  {
-      "padded": [
-          ".......................and now",
-          "......for something completely",
-          ".....................different"
-      ]
-  }
-  ```
+There are two approaches to using libraries with native dependencies...
 
-Finally, note that while most `npm` packages install JavaScript sources on 
`npm install`, some also install and compile binary artifacts. The archive file 
upload currently does not support binary dependencies but rather only 
JavaScript dependencies. Action invocations may fail if the archive includes 
binary dependencies.
+1. Run `npm install` inside a Docker container from the platform images.
+2. Building custom runtime image with libraries pre-installed.
 
-### Package an action as a single bundle
+**The first approach is easiest but can only be used when a zip file 
containing all source files and libraries is less than the action size limit 
(48MB).**
 
-It is convenient to only include the minimal code into a single `.js` file 
that includes dependencies. This approach allows for faster deployments, and in 
some circumstances where packaging the action as a zip might be too large 
because it includes unnecessary files.
+#### Running `npm install` inside runtime container
 
-You can use a JavaScript module bundler such as 
[webpack](https://webpack.js.org/concepts/). When webpack processes your code, 
it recursively builds a dependency graph that includes every module that your 
action needs.
+ - Run the following command to bind the local directory into the runtime 
container and run `npm install`.
 
-Here is a quick example using webpack:
+```
+docker run -it -v $PWD:/nodejsAction openwhisk/action-nodejs-v10 "npm install"
+```
+ This will leave a `node_modules` folder with native dependencies compiled for 
correct runtime.
 
-Taking the previous example `package.json` add `webpack` as a development 
dependency and add some npm script commands.
-```json
-{
-  "name": "my-action",
-  "main": "dist/bundle.js",
-  "scripts": {
-    "build": "webpack --config webpack.config.js",
-    "deploy": "wsk action update my-action dist/bundle.js --kind nodejs:8"
-  },
-  "dependencies": {
-    "left-pad": "1.1.3"
+ - Zip up the action source files including `node_modules` directory.
+
+```
+zip -r action.zip *
+```
+
+- Create new action with action archive.
+
+```
+ibmcloud wsk action create my-action --kind nodejs:10 action.zip
+```
+
+#### Building custom runtime image
+
+- Create a `Dockerfile` with the `npm install` command run during build.
+
+```
+FROM openwhisk/action-nodejs-v10
+
+RUN npm install <LIB_WITH_NATIVE_DEPS>
+```
+
+- Build and push the image to Docker Hub.
+
+```
+$ docker build -t <USERNAME>/custom-runtime .
+$ docker push <USERNAME>/custom-runtime
+```
+
+- Create new action using custom runtime image.
+
+```
+ibmcloud wsk action create my-action --docker <USERNAME>/custom-runtime 
action.zip
+```
+
+**Make sure the `node_modules` included in the `action.zip` does not include 
the same libraries folders.**
+
+## Using JavaScript Bundlers to package action source files
+
+Using a JavaScript module bundler can transform application source files (with 
external dependencies) into a single compressed JavaScript file. This can lead 
to faster deployments, lower cold-starts and allow you to deploy large 
applications where individual sources files in a zip archive are larger than 
the action size limit.
+
+Here are the instructions for how to use three popular module bundlers with 
the Node.js runtime. The "left pad" action example will be used as the source 
file for bundling along with the external library.
+
+### Using rollup.js ([https://rollupjs.org](https://rollupjs.org))
+
+- Re-write the `index.js` to use ES6 Modules, rather than CommonJS module 
format.
+
+```javascript
+import leftPad from 'left-pad';
+
+function myAction(args) {
+  const lines = args.lines || [];
+  return { padded: lines.map(l => leftPad(l, 30, ".")) }
+}
+
+export const main = myAction
+```
+
+*Make sure you export the function using the `const main = ...` pattern. Using 
`export {myAction as main}` does not work due to tree-shaking. See this [blog 
post](https://boneskull.com/rollup-for-javascript-actions-on-openwhisk/) for 
full details on why this is necessary.*
+
+- Create the Rollup.js configuration file in `rollup.config.js` with the 
following contents.
+
+```javascript
+import commonjs from 'rollup-plugin-commonjs';
+import resolve from 'rollup-plugin-node-resolve';
+
+export default {
+  input: 'index.js',
+  output: {
+    file: 'bundle.js',
+    format: 'cjs'
   },
-  "devDependencies": {
-    "webpack": "^3.8.1"
-  }
+  plugins: [
+    resolve(),
+    commonjs()
+  ]
+};
+```
+
+- Install the Rollup.js library and plugins using NPM.
+
+```
+npm install rollup rollup-plugin-commonjs rollup-plugin-node-resolve --save-dev
+```
+
+- Run the Rollup.js tool using the configuration file.
+
+```
+npx rollup --config
+```
+
+- Create an action using the bundle source file.
+
+```
+wsk action create my-action bundle.js --kind nodejs:10
+```
+
+- Invoke the action as normal. Results should be the same as the example above.
+
+```
+wsk action invoke my-action --result --param lines "[\"and now\", \"for 
something completely\", \"different\" ]"
+```
+
+### Using webpack ([https://webpack.js.org/](https://webpack.js.org/))
+
+- Change `index.js` to export the `main` function using as a global reference.
+
+```javascript
+const leftPad = require('left-pad');
+
+function myAction(args) {
+  const lines = args.lines || [];
+  return { padded: lines.map(l => leftPad(l, 30, ".")) }
 }
+
+global.main = myAction
 ```
 
-Create the webpack configuration file `webpack.config.js`.
+This allows the bundle source to "break out" of the closures Webpack uses when 
defining the modules.
+
+- Create the Webpack configuration file in `webpack.config.js` with the 
following contents.
+
 ```javascript
-var path = require('path');
 module.exports = {
   entry: './index.js',
+  target: 'node',
   output: {
-    path: path.resolve(__dirname, 'dist'),
     filename: 'bundle.js'
-  },
-  target: 'node'
+  }
 };
 ```
 
-Set the variable `global.main` to the main function of the action.
-From the previous example:
+- Install the Webpack library and CLI using NPM.
+
+```
+npm install webpack-cli --save-dev
+```
+
+- Run the Webpack tool using the configuration file.
+
+```
+npx webpack --config webpack.config.js
+```
+
+- Create an action using the bundle source file.
+
+```
+wsk action create my-action dist/bundle.js --kind nodejs:10
+```
+
+- Invoke the action as normal. Results should be the same as the example above.
+
+```
+wsk action invoke my-action --result --param lines "[\"and now\", \"for 
something completely\", \"different\" ]"
+```
+
+### Using parcel ([https://parceljs.org/](https://parceljs.org/))
+
+- Change `index.js` to export the `main` function using as a global reference.
+
 ```javascript
+const leftPad = require('left-pad');
+
 function myAction(args) {
-    const leftPad = require("left-pad")
-    const lines = args.lines || [];
-    return { padded: lines.map(l => leftPad(l, 30, ".")) }
+  const lines = args.lines || [];
+  return { padded: lines.map(l => leftPad(l, 30, ".")) }
 }
-global.main = myAction;
-```
 
-If your function name is `main`, use this syntax instead:
-```javascript
-global.main = main;
+global.main = myAction
 ```
 
-To build and deploy an OpenWhisk Action using `npm` and `webpack`:
+This allows the bundle source to "break out" of the closures Parcel uses when 
defining the modules.
 
-1. First, install dependencies locally:
+- Install the Parcel library using NPM.
 
-  ```
-  npm install
-  ```
+```
+npm install parcel-bundler --save-dev
+```
 
-2. Build the webpack bundle:
+- Run the Parcel tool using the configuration file.
 
-  ```
-  npm run build
-  ```
+```
+ npx parcel index.js
+```
 
-  The file `dist/bundle.js` is created, and is used to deploy as the Action 
source code.
+- Create an action using the bundle source file.
 
-3. Create the Action using the `npm` script or the CLI.
-  Using `npm` script:
-  ```
-  npm run deploy
-  ```
+```
+wsk action create my-action dist/index.js --kind nodejs:10
+```
 
-  Using the CLI:
-  ```
-  wsk action update my-action dist/bundle.js
-  ```
+- Invoke the action as normal. Results should be the same as the example above.
 
-Finally, the bundle file that is built by `webpack` doesn't support binary 
dependencies but rather JavaScript dependencies. So Action invocations will 
fail if the bundle depends on binary dependencies, because this is not included 
with the file `bundle.js`.
+```
+wsk action invoke my-action --result --param lines "[\"and now\", \"for 
something completely\", \"different\" ]"
+```
 
 
 ## Reference
@@ -397,9 +532,3 @@ The Node.js version 10.13.0 environment is used if the 
`--kind` flag is explicit
 The following packages are pre-installed in the Node.js version 10 environment:
 
 - [openwhisk v3.18.0](https://www.npmjs.com/package/openwhisk) - JavaScript 
client library for the OpenWhisk platform. Provides a wrapper around the 
OpenWhisk APIs.
-
-### Packaging npm packages with your actions
-For any `npm` packages that are not pre-installed in the Node.js environment, 
you can bundle them as dependencies when you create or update your action.
-
-For more information, see [Packaging an action as a Node.js 
module](./actions.md#packaging-an-action-as-a-nodejs-module) or [Packaging an 
action as a single bundle](./actions.md#packaging-an-action-as-a-single-bundle).
-

Reply via email to