<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>openfaas Archives - gj</title>
	<atom:link href="https://blog.gaiterjones.com/tag/openfaas/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.gaiterjones.com/tag/openfaas/</link>
	<description>gaiterjones</description>
	<lastBuildDate>Wed, 22 Nov 2017 11:52:27 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.3</generator>
	<item>
		<title>How to Deploy OpenFaaS Serverless PHP Functions</title>
		<link>https://blog.gaiterjones.com/how-to-deploy-open-faas-serverless-php-functions/</link>
					<comments>https://blog.gaiterjones.com/how-to-deploy-open-faas-serverless-php-functions/#respond</comments>
		
		<dc:creator><![CDATA[PAJ]]></dc:creator>
		<pubDate>Mon, 20 Nov 2017 15:29:57 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Open FaaS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[openfaas]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">http://blog.gaiterjones.com/?p=1779</guid>

					<description><![CDATA[If you follow Alex Ellis on Twitter one acronym that you will have been seeing a lot in your Twitter feed lately is FaaS. Alex is a pretty smart chappy...<a class="more-link" href="https://blog.gaiterjones.com/how-to-deploy-open-faas-serverless-php-functions/" title="Continue reading">Continue reading</a>]]></description>
										<content:encoded><![CDATA[<p>If you follow <a href="https://blog.alexellis.io/">Alex Ellis</a> on <a href="https://twitter.com/alexellisuk">Twitter</a> one acronym that you will have been seeing a lot in your Twitter feed lately is <strong>FaaS</strong>. Alex is a pretty smart chappy who does a lot of cool stuff with Docker, Amazon Alexa and his <a href="https://blog.alexellis.io/iot-growbox/">Raspberry Pi</a>. This year he has been developing <a href="https://www.openfaas.com/"><strong>OpenFaaS</strong></a> an open source <em>functions as a service</em> framework.</p>
<h1>What is OpenFaaS?</h1>
<p>OpenFaaS lets you build and distribute &#8220;serverless&#8221; functions in a cloud computing environment. The &#8220;function&#8221; could be simple application logic that you program &#8211; or execution of a binary to perform an action. The term serverless is a slight misnomer as you still require a server, or indeed many servers, but by deploying your function into the cloud you don&#8217;t have to worry about scaling or managing physical server resources yourself &#8211; which is pretty cool.</p>
<p>OpenFaaS works by packaging your function up into a docker container customised to work with OpenFaaS. The OpenFaaS framework stack handles the creation and deployment of the container allowing you to execute your function with a simple command line or http request.</p>
<p>OpenFaaS doesn&#8217;t really care how you create your function as long as the container behaves in the way the framework and the <em>function watchdog</em> expects. This means whilst OpenFaaS ships with support for languages like Python and NODE.js it should work with just about anything you throw at it which means you can package up just about anything as a serverless function.</p>
<p>I&#8217;m developing with good old PHP so the first thing I did when I decided to take a closer look at OpenFaaS was to google &#8220;open faas php&#8221; to see how I could create serverless functions written in PHP. My search led me to a php template for OpenFaaS developed by <a href="https://github.com/itscaro/openfaas-template-php">Minh-Quan Tran</a>. The template tells OpenFaaS how to build PHP5 or PHP7 containers to run your PHP code as OpenFaaS functions. After trying out the template there were a couple of issues with it I wanted to address, so I forked it and made a few changes. </p>
<p>If you want to deploy OpenFaaS PHP functions here&#8217;s a step by step guide that will get you from Zero to Hero in just a few minutes.</p>
<h1>Install the OpenFaaS Stack and CLI</h1>
<p>Assuming you already have Docker installed, the first thing you need to do is initialise a Docker swarm and deploy the OpenFaaS stack.</p>
<pre class="brush: bash; title: ; notranslate">
docker swarm init --advertise-addr $(hostname -i)
</pre>
<p>Change into a suitable working folder and install the OpenFaaS stack by cloning it from github and executing the deploy script.</p>
<pre class="brush: bash; title: ; notranslate">
git clone https://github.com/openfaas/faas &amp;&amp; \
  cd faas &amp;&amp; \
  ./deploy_stack.sh
</pre>
<p>Test that the stack is working by invoking the echoit example function that echoes back any input data you send it.</p>
<pre class="brush: bash; title: ; notranslate">
curl 127.0.0.1:8080/function/func_echoit -d 'hello world'
</pre>
<p>Now that OpenFaaS is working you need to install the OpenFaaS cli framework (faas-cli) that allows you to build, deploy and invoke your own functions easily from the command line.</p>
<pre class="brush: bash; title: ; notranslate">
curl -sL https://cli.openfaas.com | sudo sh
</pre>
<p>Next install the OpenFaaS PHP template</p>
<pre class="brush: bash; title: ; notranslate">
faas-cli template pull https://github.com/gaiterjones/openfaas-template-php
</pre>
<pre>
2017/11/19 09:52:30 Attempting to expand templates from master.zip
2017/11/19 09:52:30 Fetched 2 template(s) :  from https://github.com/gaiterjones/openfaas-template-php
2017/11/19 09:52:30 Cleaning up zip file...
</pre>
<h1>Build and Deploy a PHP OpenFaaS function</h1>
<p>Once the template is installed we can test it by creating our first PHP function. The OpenFaaS command line syntax for creating a new function is <strong>faas-cli new <em>functionname</em> &#8211;lang <em>languagename</em></strong>. The PHP template uses the language name <em>php</em> for PHP7 functions and <em>php5</em> for PHP5 functions. We will create a PHP7 function called func_php1 using the code in the template.</p>
<pre class="brush: bash; title: ; notranslate">
faas-cli new func_php1 --lang php
</pre>
<pre>
Folder: func_php1 created.
  ___                   _____           ____
 / _ \ _ __   ___ _ __ |  ___|_ _  __ _/ ___|
| | | | '_ \ / _ \ '_ \| |_ / _` |/ _` \___ \
| |_| | |_) |  __/ | | |  _| (_| | (_| |___) |
 \___/| .__/ \___|_| |_|_|  \__,_|\__,_|____/
      |_|


Function created in folder: func_php1
Stack file written: func_php1.yml
</pre>
<p>You will notice a new stack file func_php1.yml and function folder is created. For my tests using an Ubuntu virtual machine I had to edit func_php1.yml and change the hostname localhost to 127.0.0.1 as shown below.</p>
<pre>
provider:
  name: faas
  gateway: http://127.0.0.1:8080

functions:
  func_php1:
    lang: php
    handler: ./func_php1
    image: func_php1
</pre>
<p>In the func_php1 folder you will see three files</p>
<p> composer.json<br />
 Handler.php<br />
 php-extension.sh</p>
<p><code>Handler.php</code> contains the entrypoint for our OpenFaaS PHP function and looks like this</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

class Handler
{
    public function handle(string $_data): void {
        $_version = phpversion();
        echo 'PHP Version : '. $_version .&quot;\n&quot;. 'Data : '. $_data. &quot;\n\n&quot;;
    }
}
</pre>
<p>You can see the PHP method <code>Handler::handle()</code> is going to echo the PHP version, and whatever data is supplied to it from STDIN.</p>
<p>Build the service container for the function with</p>
<pre class="brush: bash; title: ; notranslate">
faas-cli build -f func_php1.yml
</pre>
<p>Once the container has been built deploy it with</p>
<pre class="brush: bash; title: ; notranslate">
faas-cli deploy -f func_php1.yml
</pre>
<pre>
Deploying: func_php1.
No existing function to remove
Deployed.
URL: http://127.0.0.1:8080/function/func_php1

200 OK
</pre>
<p>And that&#8217;s it, our PHP OpenFaaS function is ready to test we can invoke it from faas-cli</p>
<pre class="brush: bash; title: ; notranslate">
faas-cli invoke -f func_php1.yml func_php1
</pre>
<p>Or use curl</p>
<pre class="brush: bash; title: ; notranslate">
curl 127.0.0.1:8080/function/func_php1 -d 'hello world'
</pre>
<pre>
PHP Version : 7.1.11
Data : hello world
</pre>
<p>You can also access all functions via the nifty OpenFaaS UI at http://yourhost/:8080/ui/</p>
<h1>Build and Deploy a GEO IP OpenFaaS PHP function</h1>
<p>Now let&#8217;s deploy a function with a little more functionality&#8230;</p>
<p>One API I use a lot is <a href="https://github.com/maxmind/GeoIP2-php" rel="noopener" target="_blank">GEOIP2 by MaxMind</a> it&#8217;s very useful for getting geographic data from an IP address. So let&#8217;s build an OpenFaaS PHP function to do just that.</p>
<p>Create a new PHP7 function called func_geoip</p>
<pre class="brush: bash; title: ; notranslate">
faas-cli new func_geoip --lang php
</pre>
<p>Before building the function we need to add our PHP code and dependencies. First let&#8217;s add the PHP dependencies to the functions composer file by editing <em>func_geoip/composer.json</em></p>
<pre class="brush: plain; title: ; notranslate">
{
    &quot;name&quot;: &quot;function-php7&quot;,
    &quot;description&quot;: &quot;OpenFaaS GEOIP PHP function&quot;,
    &quot;type&quot;: &quot;project&quot;,
    &quot;license&quot;: &quot;MIT&quot;,
    &quot;require&quot;: {
        &quot;php&quot;: &quot;^7.0&quot;,
        &quot;maxmind-db/reader&quot;: &quot;~1.0&quot;,
        &quot;geoip2/geoip2&quot;: &quot;~2.0&quot;
    }
}
</pre>
<p>The geo ip data is read from a free <a href="http://dev.maxmind.com/geoip/geoip2/geolite2/">GEOLITE2 database</a> so we need to make that database available to our function. We can add data to our container using the <em>func_geoip/php-extension.sh</em> shell file which is executed when we build the template container.</p>
<pre class="brush: bash; title: ; notranslate">
echo &quot;Installing function dependencies&quot;
cd /usr/local/faas/function
curl -o GeoLite2-City.tar.gz http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz
tar -xvzf GeoLite2-City.tar.gz --strip 1
</pre>
<p>Now add the geo ip lookup code to our PHP Handler class by editing <code>func_geoip/Handler.php</code></p>
<span class="collapseomatic collapse" id="id6613413f25b06"  tabindex="0" title="Handler.php"    >Handler.php</span><div id="target-id6613413f25b06" class="collapseomatic_content ">
[php]
&lt;?php<br />
use GeoIp2\Database\Reader;</p>
<p>class Handler<br />
{<br />
    public function handle(string $_data): void {</p>
<p>        echo json_encode($this-&gt;geoIPLookup($_data));</p>
<p>    }</p>
<p>    protected function geoIPLookup($_ip)<br />
	{<br />
		$_reader = new Reader(&#8216;/usr/local/faas/function/GeoLite2-City.mmdb&#8217;);</p>
<p>			try // &amp; get geoip info<br />
			{<br />
				$_record = $_reader-&gt;city($_ip);</p>
<p>				$_geoIPData=array(<br />
					&#8216;ip&#8217; =&gt; $_ip,<br />
					&#8216;country&#8217; =&gt; $_record-&gt;country-&gt;name,<br />
					&#8216;isocode&#8217; =&gt; $_record-&gt;country-&gt;isoCode,<br />
					&#8216;region&#8217; =&gt; $_record-&gt;mostSpecificSubdivision-&gt;name,<br />
					&#8216;city&#8217; =&gt; $_record-&gt;city-&gt;name,<br />
					&#8216;postcode&#8217; =&gt; $_record-&gt;postal-&gt;code,<br />
					&#8216;latitude&#8217; =&gt; $_record-&gt;location-&gt;latitude,<br />
					&#8216;longitude&#8217; =&gt; $_record-&gt;location-&gt;longitude,<br />
					&#8216;googlemap&#8217; =&gt; &#8216;https://maps.google.com/?q=&#8217;. $_record-&gt;location-&gt;latitude. &#8216;,&#8217;. $_record-&gt;location-&gt;longitude<br />
				);<br />
			}<br />
			catch (\Exception $e)<br />
			{<br />
				$_geoIPData=array(<br />
					&#8216;ip&#8217; =&gt; $_ip,<br />
					&#8216;country&#8217; =&gt; &#8216;Not Found&#8217;,<br />
					&#8216;isocode&#8217; =&gt; &#8216;Not Found&#8217;,<br />
					&#8216;region&#8217; =&gt; &#8216;Not Found&#8217;,<br />
					&#8216;city&#8217; =&gt; &#8216;Not Found&#8217;,<br />
					&#8216;postcode&#8217; =&gt; &#8216;Not Found&#8217;,<br />
					&#8216;latitude&#8217; =&gt; &#8216;Not Found&#8217;,<br />
					&#8216;longitude&#8217; =&gt; &#8216;Not Found&#8217;,<br />
					&#8216;googlemap&#8217; =&gt; &#8216;Not Found&#8217;,<br />
                    &#8216;exception&#8217; =&gt; $e-&gt;getMessage()<br />
				);<br />
			}</p>
<p>		unset($_reader);</p>
<p>		return ($_geoIPData);</p>
<p>	}<br />
}<br />
[/php]
</div>
<p>Build and deploy the function</p>
<pre class="brush: bash; title: ; notranslate">
faas-cli build -f func_geoip.yml
faas-cli deploy -f func_geoip.yml
</pre>
<p>Now we can test it with</p>
<pre class="brush: bash; title: ; notranslate">
curl 127.0.0.1:8080/function/func_geoip -d '128.101.101.101'
</pre>
<p>The function returns the JSON formatted array of Geo data for the requested IP address</p>
<pre>
{"ip":"128.101.101.101","country":"United States","isocode":"US","region":"Minnesota","city":"Minneapolis","postcode":"55414","latitude":44.9759,"longitude":-93.2166,"googlemap":"https:\/\/maps.google.com\/?q=44.9759,-93.2166"}
</pre>
<h1>FaaS in Production</h1>
<p>We can easily access function data from other PHP applications using php curl to post the input data and return the output array. In production you need to consider how you will secure access to the function using some form of frontend proxy authentication.</p>
<p>Whether you will deploy simple php code as serverless functions in this way depends very much on the type of applications you are developing and the infrastructure available to you. I can<br />
 certainly think of a lot of my commonly used PHP library functions and classes that would become very useful deployed as OpenFaaS serverless functions.</p>
<h1>References</h1>
<ul>
<li><a href="https://www.openfaas.com/" rel="noopener" target="_blank">OpenFaaS</a></li>
<li><a href="https://github.com/openfaas/faas/blob/master/community.md" rel="noopener" target="_blank">OpenFaaS Community</a></li>
<li><a href="https://blog.alexellis.io/quickstart-openfaas-cli/" rel="noopener" target="_blank">OpenFaaS CLI</a></li>
<li><a href="https://github.com/gaiterjones/openfaas-template-php" rel="noopener" target="_blank">PHP Template</a></li>
<li><a href="https://docs.docker.com/engine/swarm/swarm-tutorial/" rel="noopener" target="_blank">Docker Swarm Tutorial</a></li>
</ul>
<h1>Tested on</h1>
<ul>
<li>Ubuntu Server 17.10</li>
<li>Docker 17.09.0-ce</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.gaiterjones.com/how-to-deploy-open-faas-serverless-php-functions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
