Search code examples
pythondockeropenwhisk

How do I make a Python Docker image an OpenWhisk action?


I have a Docker image which runs a Python program. I want now to run this container as an OpenWhisk action. How do I do this?

I have seen several examples in other programming languages, and an excellent black box skeleton approach in C and Node.js. but I want to understand more about how OpenWhisk interacts with the container and, if possible, employ just Python.


Solution

  • It's a lot simpler now (Sept 2016) than in my previous answer.

    After having created the dockerSkeleton directory with the command $ wsk sdk install docker all you have to do is to edit the Dockerfile and make sure your Python (2.7 right now) is accepting parameters and supplying outputs in the appropriate format.

    Here's a summary. I've written it up in greater detail here on GitHub

    The program

    File test.py (or whatever_name.py you will use in your edited Dockerfile below.)

    • Make sure it's executable (chmod a+x test.py).
    • Make sure it's got the shebang on line one.
    • Make sure it runs locally.
      • e.g. ./test.py '{"tart":"tarty"}'
        produces the JSON dictionary:
        {"allparams": {"tart": "tarty", "myparam": "myparam default"}}
     
        #!/usr/bin/env python
    
        import sys
        import json
    
        def main():
          # accept multiple '--param's
          params = json.loads(sys.argv[1])
          # find 'myparam' if supplied on invocation
          myparam = params.get('myparam', 'myparam default')
    
          # add or update 'myparam' with default or 
          # what we were invoked with as a quoted string
          params['myparam'] = '{}'.format(myparam)
    
          # output result of this action
          print(json.dumps({ 'allparams' : params}))
    
        if __name__ == "__main__":
          main()
     

    The Dockerfile

    Compare the following with the supplied Dockerfile to take the Python script test.py and ready it to build the docker image.

    Hopefully the comments explain the differences. Any assets (data files or modules) in the current directory will become part of the image as will any Python dependencies listed in requirements.txt

    # Dockerfile for Python whisk docker action
    FROM openwhisk/dockerskeleton
    
    ENV FLASK_PROXY_PORT 8080
    
    # Install our action's Python dependencies
    ADD requirements.txt /action/requirements.txt
    RUN cd /action; pip install -r requirements.txt
    
    # Ensure source assets are not drawn from the cache 
    # after this date
    ENV REFRESHED_AT 2016-09-05T13:59:39Z
    # Add all source assets
    ADD . /action
    # Rename our executable Python action
    ADD test.py /action/exec
    
    # Leave CMD as is for Openwhisk
    CMD ["/bin/bash", "-c", "cd actionProxy && python -u actionproxy.py"]
    

    Note the ENV REFRESHED_AT ... which I used to make sure that an updated test.py layer is picked up afresh rather than being drawn from the cache when the image is built.