PHP and OpenFaaS
There’s been a couple of things recently that have got me to this point
- Hype around serverless functions
- My growing interest in OpenFaaS
So here I am, sat in a coffee shop in central London tinkering with OpenFaaS and PHP - here’s how it went.
OpenFaaS describes itself as “Serverless Functions Made Simple for Docker & Kubernetes”
Within this post, I’m not saying any of this is perfect or the best way to do things. This is just documentation of what I did and my own personal notes of things I’ve found along the way to getting a PHP serverless function running locally in OpenFaaS. This is mostly a brain-dump for my own reference later on.
Setting up OpenFaaS
Get OpenFaaS setup and running as per the docs. I did mine locally just to tinker with it. I already had docker running so I ran docker swarm init
and then ran:
> git clone https://github.com/openfaas/faas && \
cd faas && \
./deploy_stack.sh
Which deployed it and gave me some admin credentials. I opened the UI at 127.0.0.1:8080
and used them to login.
Get OpenFaaS CLI up and running as per the docs. - I used brew install faas-cli
as I was on my Macbook at the time.
Setting up our project
Make a new directory for your serverless function:
> mkdir ping-php && cd ping-php
Now pull the template we’re going to use (thanks to itscaro for this!
> faas-cli template pull https://github.com/itscaro/openfaas-template-php
Now we’ll create a new function and tell it what language to use:
> faas-cli new ping-php --lang php
Now open the directory within your editor of choice. Mine’s PhpStorm.
The first thing of note that’s odd to me is the nested folders of the same name. But hey, we’ll roll with it.
Within ./ping-php
there’s a src
directory that containers a Handler.php
class. Open that and you’ll see:
<?php
namespace App;
class Handler
{
public function handle(string $data): void {
echo $data;
}
}
So, by default it’ll just return the data you send to it.
Now we’ve got the project setup, we can build it!
Building our function
To build your function, we’ll use the faas-cli
once again:
> faas-cli build -f ./ping-php.yml
This will build the docker container that will run our function.
Once it’s built, we can deploy it!
Deploying our function
> faas-cli deploy -f ./ping-php.yml
After running this function you should see:
Deploying: ping-php.
Deployed. 200 OK.
URL: http://127.0.0.1:8080/function/ping-php
This tells us that it’s deployed okay, as well as the URL we can invoke the function with.
Running our function
Now, we can access our function by sending a POST
request to the URL specified:
> curl -XPOST http://127.0.0.1:8080/function/ping-php
However, we’ll not see anything as the function just returns what you submit to it, and we haven’t sent anything to it!
Now, if we submit data to it, we should have the data returned. So running:
> curl -XPOST -d "hello blog\!" http://127.0.0.1:8080/function/ping-php
Will give us an output of:
hello blog!
Winner!
Now, let’s update our function to respond with the current timestamp as it’s a “ping” function.
Updating our function
Let’s update our function to return some json, so back in ./ping-php/src/Handler.php
we’ll change it to:
<?php
namespace App;
class Handler
{
public function handle(string $data): void {
echo json_encode(['pong' => time()]);
}
}
Note that we’re not setting a
Content-Type
. From my playing around it seems that setting aContent-Type
within the function that’s responding doesn’t do anything. The gateway that OpenFaaS uses though does seem to respect theContent-Type
in the request and use that for the response. Digging through the docs there’s more information there that suggests that’s the case.
We can verify this by running:
> curl -XPOST -H "Content-Type: application/json" http://127.0.0.1:8080/function/ping-php --head
Which will show us that the response also gives back application/json
:
HTTP/1.1 200 OK
Content-Length: 19
Content-Type: application/json
Date: Sat, 21 Jul 2018 12:35:58 GMT
X-Call-Id: 155bd285-8ea9-413d-a60b-d66adac0b676
X-Duration-Seconds: 0.018977
X-Start-Time: 1532176558927224600
Right back to it, let’s re-build our function and re-deploy it as per the steps above:
Build:
> faas-cli build -f ./ping-php.yml
Deploy:
> faas-cli deploy -f ./ping-php.yml
Now if we run our function, we’ll see that we get back the JSON we specified:
> curl -XPOST http://127.0.0.1:8080/function/ping-php
{"pong":1532176701}
Conclusion
First impressions: cool!
Interested to see how it works in production if I move anything to it. Like anything, I expect it to have a learning cliff - everything in dev is easy, prod is always another matter! But that’s future Matts problem, present-Matt is just having fun with the easy stuff in dev