Make your own Linux command Function with HotWrap and a Customer Docker Image
This tutorial walks through how to use a custom Docker image to define an Fn function. Although Fn functions are packaged as Docker images, when developing functions using the Fn CLI developers are not directly exposed to the underlying Docker platform. Docker isn’t hidden (you can see Docker build output and image names and tags), but you aren’t required to be very Docker-savvy to develop functions with Fn.
What if you want to make a function using Linux command line tools, or a script that does not involve one of the supported Fn languages? Can you use your Docker image as a function? Fortunately the design and implementation of Fn enables you to do exactly that. Let’s build a simple custom function container image to see how it’s done.
As you make your way through this tutorial, look out for this icon. Whenever you see it, it’s time for you to perform an action.
This tutorial requires you to have both Docker and Fn installed. If you need help with Fn installation you can find instructions in the Install and Start Fn Tutorial.
If it isn’t already running, you’ll need to start the Fn server. We’ll run it in the foreground to let us see the server log messages so let’s open a new terminal for this.
Start the Fn server using the
Fn HotWrap Tool
The Fn HotWrap tool allows you to create functions using conventional Unix command line tools and a Docker container. The tool provides the FDK contract for any command that can be run on the command line. Once wrapped, event data is passed to your function via STDIN and the output is returned through STDOUT.
Initial Linux Command
To begin with, let’s use the Linux
rev command. The command reverses text, so this command:
echo "Hello World" | rev
So we only need to call the command
/bin/rev for our function.
Create Function Directory and Metadata
Next we need a directory for our project.
Create a folder named revfunc. Change into the folder.
In the folder , create a
func.yamlfile and copy/paste the following as its content:
schema_version: 20180708 name: revfunc version: 0.0.1 runtime: docker triggers: - name: revfunc type: http source: /revfunc
This is a typical
func.yaml except that instead of declaring the runtime
as a programming language we’ve specified “docker”. If you were to type
build right now you’d get the error:
Fn: Dockerfile does not exist for ‘docker’ runtime
This is because when you set the runtime type to “docker”. The
command defers to your Dockerfile to build the function container image–and you
haven’t defined one yet!
Create a Function Dockerfile
Now you need to create a
Create a file named
Dockerfileand copy/paste the following as its content:
FROM alpine:latest # Install hotwrap binary in your container COPY --from=fnproject/hotwrap:latest /hotwrap /hotwrap CMD "/bin/rev" ENTRYPOINT ["/hotwrap"]
Here is an explanation of each of the Docker commands.
FROM alpine:latest- Use the latest version of Alpine Linux as the base image.
COPY --from=fnproject/hotwrap:latest /hotwrap /hotwrap- Install the HotWrap Fn tool.
CMD "/bin/rev"- The Linux command to run.
ENTRYPOINT ["/hotwrap"]- Tells the container to execute the previous command using HotWrap:
Building and Deploying
Once you have your custom Dockerfile you can simply use
fn build to build
your function. Give it a try:
fn -v build
You should see output similar to:
Building image fndemouser/revfunc:0.0.1 FN_REGISTRY: fndemouser Current Context: default Sending build context to Docker daemon 3.072kB Step 1/4 : FROM alpine:latest latest: Pulling from library/alpine 9d48c3bd43c5: Pull complete Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb Status: Downloaded newer image for alpine:latest ---> 961769676411 Step 2/4 : COPY --from=fnproject/hotwrap:latest /hotwrap /hotwrap latest: Pulling from fnproject/hotwrap e6b890787691: Pull complete Digest: sha256:bf6303d7d216581c0e760f33dd74c3cdea83edad69f3d9614b7f573ba62c22b4 Status: Downloaded newer image for fnproject/hotwrap:latest ---> b999e7d793ff Step 3/4 : CMD "/bin/rev" ---> Running in b60971040cd0 Removing intermediate container b60971040cd0 ---> 5fa7a768081c Step 4/4 : ENTRYPOINT ["/hotwrap"] ---> Running in 693c2d86cb7e Removing intermediate container 693c2d86cb7e ---> 34d833b6acc2 Successfully built 34d833b6acc2 Successfully tagged fndemouser/revfunc:0.0.1
Just like with a default build, the output is a container image. From this point forward everything is just as it would be for any Fn function. Since you’ve previously started an Fn server, you can deploy it. First, create an application named ‘revapp’.
Create an application:
fn create app revapp
Next, deploy your function to that app.
Deploy the function to the application:
fn deploy --app revapp --local --no-bump
We can confirm the function is correctly defined by getting a list of the functions in the “revapp” application:
fn list functions revapp
You should get output similar to:
NAME IMAGE ID revfunc fndemouser/revfunc:0.0.1 01DQ8R97QTNG8G00GZJ0000002
Pro tip: The Fn cli let’s you abbreviate most of the keywords so you can
fn ls f revapp! You should see the same output.
Invoking the Function
With the function deployed let’s invoke it to make sure it’s working as expected.
echo "Hello World" | fn invoke revapp rev-func
For this command you should see the following output:
Calling the Function with curl
We included an HTTP trigger declaration in the
func.yaml so we can also call
the function with
curl --data "Hello World" -H "Content-Type: text/plain" -X POST http://localhost:8080/t/revapp/revfunc
You should get exactly the same output as when using
One of the most powerful features of Fn is the ability to use custom defined Docker container images as functions. This feature makes it possible to customize your function’s runtime environment including letting you use Linux command line tools as your function. And thanks to the Fn CLI’s support for Dockerfiles it’s the same user experience as when developing any function.
Having completed this tutorial you’ve successfully built a function using a custom Dockerfile. Congratulations!
Go: Back to Contents