Getting started with Fn Project

Peter Jausovec
Sep 19, 2018 · 6 min read
Image for post
Image for post
“brown track and field” by Adi Goldstein

I am not one of those lucky ones who can simply read a whitepaper/code/docs and can quickly figure out how things work without trying things out in practice. I need to install things, run things and play with them to get a feeling for how stuff works. If I get stuck, that’s when I am going to read the docs and code to see what I am missing.

In this series, I decided to figure out how Fn project works, how to run it, use it and even extend it. Fn project is a container native, cloud agnostic serverless platform.

The Basics — install and run

This section goes through installing the Fn server, starting it and then creating a simple function and invoking it.

You will need Docker on your machine in order to run Fn and once you have that, you can install the Fn with brew:

brew install fn

Finally, with Fn installed and images updated, you can run the Fn server with the following command:

fn start

The above command runs Fn in a single server mode with an embedded database and queue. Behind the scenes, thefn start command runs a Docker image calledfnproject/fnserver in a privileged mode. It also mounts the Docker socket into the container as well as the /data folder in the current working directory (this is where database and queue information is stored). Finally, it exposes port 8080 to the host, so you can invoke it on that port.

Image for post
Image for post
fnserver image running locally

Now that you have the Fn server running, you can create a new function.

First function

The Fn CLI comes with a init command that is used for creating new functions. The Fn CLI has been installed with brew during the previous step.

Before we start, here’s a simple explanation of different concepts Fn uses:

Apps are a way to logically group your functions and triggers under the same name (e.g. greeter-app)

Triggers are pointers to functions — it’s an endpoint where the function can be invoked from, e.g.http://localhost:8080/greeter-app/hello uses an HTTP trigger. You can have multiple triggers pointing to the same function.

This is the actual piece of code you are writing and that gets executed.

Docker image that packages your function; the image used depends on the language of the function (e.g.fnproject/go, fnproject/ruby, fnproject/node, …), the goal here is that the image is as small as possible to be more performant.

With this out of the way, let’s create a new function by providing a runtime (e.g. Go, Node or any other supported language) and the name of the function:

fn init --runtime go --trigger http hello

The above command creates a Go function in the hello sub folder. The function structure looks like this:

├── Gopkg.toml
├── func.go
├── func.yaml
└── test.json

The source of your function lives inside the func.go file and has a function handler that responds with a “Hello World” message. The func.yaml file contains information such as version runtime, name, entry point for your function and a list of triggers.

Another interesting file is test.json — this file holds an array of tests (input values and expected output values) and can be used to black-box test your function by running fn test.

To run this function, you can use the fn run command. But before you run the command, make sure you set the FN_REGISTRY environment variable to your Docker repository.

Then when you run the command, Fn will build the Docker image with the function and runs the function like this:

$ fn run
Building image hello:0.0.1 ...........
{"message":"Hello World"}

This is all great, but we have the Fn server running locally, so let’s deploy our function to the server, instead of just running it.

To deploy the function, you can use the fn deploy command, specify the app name and add the --local flag since the Fn server is running locally. Note that you need to run the command below from within the function folder:

fn deploy --app myapp --local

This command deploys the app (called myapp) and a function called helloto the local Fn server and links a trigger called hello-trigger to that function.

Image for post
Image for post
Deploying the app to local Fn server

This means that on the Fn server, the function will be accessible under /myapp/hello-trigger path (e.g. http://localhost:8080/t/myapp/hello-trigger). The app name is used to logically group functions together. To see the full list of triggers defined on the Fn server, just run this command:

# List all triggers for 'myapp'
$ fn list triggers myapp
hello hello-trigger http /hello-trigger http://localhost:8080/t/myapp/hello-trigger

Finally, if you access the endpoint, you will get back the “Hello World” message like this:

$ curl http://localhost:8080/t/myapp/hello-trigger
{"message":"Hello World"}

Grouping functions

To group the functions together, you can use the app name construct — this allows you to logically group different functions together (e.g. greeter-app could have functions called hello and goodbye).

In this case, the greeter-app could also be the folder name where your functions live, and subfolders /hello and /goodbye would contain the actual functions. You can also define the app.yaml file in the app root folder, to be able to deploy all functions with one command.

Follow the steps below to create a greeter-app with hello and goodbye functions:

# Create the greeter-app folder
mkdir greeter-app && cd greeter-app
# Create app.yaml that defines the app name
echo "name: greeter-app" > app.yaml
# Create a hello function in /hello subfolder
fn init --runtime go --trigger http hello
# Create a goodbye function in /goodbye subfolder
fn init --runtime go --trigger http goodbye

Next we can go into the /hello and the /goodbye folder, and deploy each app separately with fn deploy --app greeter-app. Alternatively, since we have the app name defined in app.yaml in the root folder, we can use this command to deploy all functions to the local Fn server:

fn deploy --all --local

The above command creates the following functions and triggers:

$ fn list triggers greeter-app
goodbye goodbye-trigger http /goodbye-trigger http://localhost:8080/t/greeter-app/goodbye-trigger
hello hello-trigger http /hello-trigger http://localhost:8080/t/greeter-app/hello-trigger

You can also create a function that lives in the root of your app by running fn init command from the apps’ root folder:

fn init --runtime node --trigger http

Then deploy it again:

fn deploy --all --local

Now we have three triggers defined under the greeter-app logical group:

$ fn list triggers greeter-app
goodbye goodbye-trigger http /goodbye-trigger http://localhost:8080/t/greeter-app/goodbye-trigger
greeter-app greeter-app-trigger http /greeter-app-trigger http://localhost:8080/t/greeter-app/greeter-app-trigger
hello hello-trigger http /hello-trigger http://localhost:8080/t/greeter-app/hello-trigger

Enabling the UI

If you prefer UI to interact with Fn — there’s that for you as well. Assuming you have the Fn server running locally, you can start the UI like this:

docker run --rm -it --link fnserver:api -p 4000:4000 -e "FN_API_URL=http://api:8080" fnproject/ui

When image gets downloaded and container executes, you’ll be able to access the UI on http://localhost:4000.

Image for post
Image for post
Fn server UI


This article should serve you as a good introduction and getting started document for Fn. It gives you the basics you need to start playing with serverless functions on your local machine.

Fn Project

Learn about the Fn Project, containers, and serverless…

Thanks to David Delabassee

Peter Jausovec

Written by

Fn Project

Learn about the Fn Project, containers, and serverless computing!

Peter Jausovec

Written by

Fn Project

Learn about the Fn Project, containers, and serverless computing!

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store