<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Head in the clouds...]]></title><description><![CDATA[Thoughts, stories and ideas to pave our way to the cloud.]]></description><link>https://blog.jmkhael.io/</link><image><url>https://blog.jmkhael.io/favicon.png</url><title>Head in the clouds...</title><link>https://blog.jmkhael.io/</link></image><generator>Ghost 5.71</generator><lastBuildDate>Thu, 25 Jun 2026 16:28:26 GMT</lastBuildDate><atom:link href="https://blog.jmkhael.io/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Unleash the Artist within you with Docker, Tensorflow and OpenFaaS]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<h4 id="whaticannotcreateidonotunderstandrichardfeynman">&#x201C;What I cannot create, I do not understand.&#x201D; &#x2014; Richard Feynman</h4>
</blockquote>
<h2 id="context">Context</h2>
<p>Since my early age, I always felt incapable of drawing. My talent was miserable at best, leading me to think that drawing is more of an innate talent than a craft I can learn (in <em>short</em></p>]]></description><link>https://blog.jmkhael.io/unleash-the-artist-within-tensorflow-and-openfaas/</link><guid isPermaLink="false">653d5697cf37c50001d2406f</guid><category><![CDATA[tensorflow]]></category><category><![CDATA[openfaas]]></category><category><![CDATA[serverless]]></category><category><![CDATA[machine-learning]]></category><category><![CDATA[magenta]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Tue, 21 Nov 2017 14:52:50 GMT</pubDate><media:content url="https://blog.jmkhael.io/content/images/2017/11/vespa-faas-varied-24-1.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<h4 id="whaticannotcreateidonotunderstandrichardfeynman">&#x201C;What I cannot create, I do not understand.&#x201D; &#x2014; Richard Feynman</h4>
</blockquote>
<h2 id="context">Context</h2>
<img src="https://blog.jmkhael.io/content/images/2017/11/vespa-faas-varied-24-1.jpg" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"><p>Since my early age, I always felt incapable of drawing. My talent was miserable at best, leading me to think that drawing is more of an innate talent than a craft I can learn (in <em>short time</em> and without dedication of course!).</p>
<p>In this post, the second of the &quot;Machine Learning on Serverless&quot; blog post series, we will unleash the artist within, and prove that we can use code to generate some compelling art!</p>
<p>(In the first post of the serie we developed a serverless function to identify Doppelg&#xE4;ngers.<br>
You can read about it here: <a href="https://blog.jmkhael.io/kittens-vs-tarsiers-an-introduction-to-serverless-machine-learning/">Kittens vs Tarsiers - an introduction to serverless machine learning</a>)</p>
<p>We will be using Google Brain project <a href="https://magenta.tensorflow.org/?ref=blog.jmkhael.io">Magenta</a>, <a href="https://www.openfaas.com/?ref=blog.jmkhael.io">OpenFaaS</a> and <a href="https://www.docker.com/?ref=blog.jmkhael.io">Docker</a> to build a Serverless function which will enable us to do multi-style transfer.</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/magenta-logo-bottom-text.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://camo.githubusercontent.com/cf01eefb5b6905f3774376d6d1ed55b8f052d211/68747470733a2f2f626c6f672e616c6578656c6c69732e696f2f636f6e74656e742f696d616765732f323031372f30382f666161735f736964652e706e67" style="width: 480px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<h3 id="showmewhatitdoes">Show me what it does</h3>
<p>Let&apos;s start with a demo of what this is capable of before running through the explanation of what this is and how it works.</p>
<blockquote>
<p>The image on the left is the original one.<br>
The one on the right was stylized with one of the 40+ styles of the function we are going to discuss below.</p>
</blockquote>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/vespa-faas.jpg" style="width: 300px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/vespa-faas-varied-24.jpg" style="width: 300px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/meme-test.jpg" style="width: 300px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/varied_styles_31_1000.png" style="width: 300px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/family-ties.jpg" style="width: 300px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/varied_styles_7_1000.png" style="width: 300px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/Screenshot-from-2017-11-21-10-28-19.png" style="width: 350px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/Screenshot-from-2017-11-21-10-28-01.png" style="width: 350px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<h4 id="gordonevilmastermindbehinddocker">Gordon (Evil mastermind behind Docker)</h4>
<blockquote>
<p>Original picture of Gordon eating a strawberry in real life</p>
</blockquote>
<img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg" style="width: 300px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS">
<blockquote>
<p>9 different monet styles are available</p>
</blockquote>
<p>(open in new tab to see it bigger or just check the album for more samples <a href="https://photos.app.goo.gl/MCNnnrmlCSBwR9xH3?ref=blog.jmkhael.io">https://photos.app.goo.gl/MCNnnrmlCSBwR9xH3</a>)</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_0_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_1_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_2_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_4_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_5_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"><br>
<img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_6_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_7_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_8_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_monet_styles_9_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<blockquote>
<p>31 varied styles are also available</p>
</blockquote>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_0_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_1_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_2_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_3_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_4_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_5_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_6_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_7_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_8_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_9_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_10_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_11_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_12_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_13_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_14_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_15_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_16_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_17_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_18_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_19_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_20_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_21_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_22_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_23_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_24_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_25_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_26_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_27_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_28_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_29_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"><br>
<img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_30_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"> <img src="https://blog.jmkhael.io/content/images/2017/11/gordon-rpi.jpg_varied_styles_31_1000.png" style="width: 100px" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS"></p>
<hr>
<h3 id="whatisopenfaas">What is OpenFaaS?</h3>
<blockquote>
<p><a href="https://www.openfaas.com/?ref=blog.jmkhael.io">OpenFaaS</a> (Functions as a Service) is a framework for building serverless functions with Docker and Kubernetes which has first class support for metrics. Any process can be packaged as a function enabling you to consume a range of web events without repetitive boiler-plate coding.</p>
</blockquote>
<p>Based on it&apos;s active community adoption and it&apos;s 8k+ stars, it is the <em><strong>best</strong></em> developer experience to build serverless function for any langage you fancy!</p>
<h3 id="whatismagenta">What is Magenta?</h3>
<blockquote>
<p>Magenta is a Google Brain project to ask and answer the questions, &#x201C;Can we use machine learning to create compelling art and music? If so, how? If not, why not?&#x201D;<br>
Check it out here: <a href="https://magenta.tensorflow.org/?ref=blog.jmkhael.io">https://magenta.tensorflow.org/</a></p>
</blockquote>
<p>Magenta already has published models to generate drums tracks, image stylization, neural audio synthesis, polyphonic music generation with reinforcement learning and sketches generation!</p>
<p><img src="https://camo.githubusercontent.com/3bec492b1b85a71834226e771b3d5cd1a043d240/68747470733a2f2f63646e2e7261776769742e636f6d2f74656e736f72666c6f772f6d6167656e74612f6d61737465722f6d6167656e74612f6d6f64656c732f736b657463685f726e6e2f6173736574732f6361746275732e737667" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<blockquote>
<p>Sketch interpolation between a cat and a bus!</p>
</blockquote>
<p>In this blog post, we will focus on multi-style transfer, future blog post may focus on music or sketches generation.</p>
<h3 id="whatisstyletransferandmultistyleimagetransfer">What is style transfer and multi-style image transfer?</h3>
<p>As the proverb goes, an image is worth a thousand words. Here are a couple to show you the power of style transfer and multi-style transfer.</p>
<p>This first one, is a high level view of pastiche or style transfer.</p>
<blockquote>
<p>You take a content, you take a style, you transfer the style on the content, you get a pastiche.</p>
</blockquote>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/pastiche.png" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<p>The second one, is a high level view of style transfer.</p>
<ul>
<li>On the X axis lies different styles by William Glackens, Paul Signac, Georges Rouault, Edvard Munch and Vincent van Gogh.</li>
<li>On the Y axis we have known photographs, a.k.a. the content to be styled.</li>
</ul>
<p>The crossing between the X and Y axis is the manifestation of what style transfer can do.</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/content-vs-style.png" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<h4 id="whataboutmultistyle">What about Multi-style?</h4>
<blockquote>
<p>if one could combine many different styles, exploring unique mixtures of well known artists to create an entirely unique pastiche?</p>
</blockquote>
<p>That&apos;s what multi-style transfer is all about!<br>
<img src="https://blog.jmkhael.io/content/images/2017/11/multi-style.jpg" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<hr>
<h2 id="writingtheartistserverlessfunction">Writing the Artist serverless function</h2>
<blockquote>
<p>All the code lives in my Github repository here: <a href="https://github.com/jmkhael/faas-artist?ref=blog.jmkhael.io">https://github.com/jmkhael/faas-artist</a>, but stick around as I explain the code below.</p>
</blockquote>
<h3 id="implementation">Implementation</h3>
<p>Before starting to write our function, let&apos;s install <code>faas-cli</code> which is a very nice CLI to <code>list</code>, create <code>new</code>, <code>build</code>, <code>deploy</code>, <code>invoke</code>, <code>push</code> and <code>remove</code> functions to list a few - the CLI verbs are growing every day!</p>
<blockquote>
<p>It is the Official CLI for the OpenFaaS Serverless framework - <a href="https://github.com/alexellis/faas-cli?ref=blog.jmkhael.io">GitHub repo</a></p>
</blockquote>
<h4 id="prereqs">Pre-reqs</h4>
<p>Get the <code>faas-cli</code>, if you haven&apos;t yet. You really have to if you want to be productive!<br>
The easiest way to install the <code>faas-cli</code> is through <code>curl</code> or <code>brew</code>:</p>
<pre><code>$ curl -sSL https://cli.openfaas.com | sudo sh
</code></pre>
<p>or:</p>
<pre><code>$ brew install faas-cli
</code></pre>
<p>Start <code>faas-cli</code> and be amazed by it&apos;s ascii art and help message:<br>
<img src="https://blog.jmkhael.io/content/images/2017/09/Screenshot-from-2017-09-21-11-29-33.png" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<h2 id="scaffold">Scaffold</h2>
<p>Time to create our function. Let&apos;s use the faas-cli to do so.</p>
<pre><code>faas-cli new artist --lang python
</code></pre>
<h3 id="buildanddeploy">Build and deploy</h3>
<pre><code>faas-cli build -f artist.yml
faas-cli deploy -f artist.yml
</code></pre>
<h3 id="testthescaffoldedfunction">Test the scaffolded function</h3>
<pre><code>echo &quot;Hello, Magenta and OpenFaaS&quot; | faas-cli invoke artist
</code></pre>
<p><img src="https://blog.jmkhael.io/content/images/2017/11/Screenshot-from-2017-11-20-14-56-40.png" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<hr>
<h3 id="implementation">Implementation</h3>
<p>Now we will fill in the function to do the actual work. You can find the full code <a href="https://github.com/jmkhael/faas-artist/blob/master/artist/function/handler.py?ref=blog.jmkhael.io">on the github repository</a>.<br>
We highlight the important aspects below.</p>
<p>As shown above, magenta delivered two models:</p>
<ul>
<li><strong>monet</strong>: offers 9 styles</li>
<li><strong>varied</strong>: offers 31 styles</li>
</ul>
<p>In order to chose a given style and style index, we will pass some information as a headers to the function so we take the appropriate decision in there.<br>
We can also apply a multi-style blending several styles of a given model together, based on weights. e.g.: <code>{1:0.3, 10:0.5, 24:0.2}</code> to tell the artist to use style 1, style 10 and style 24 in the proportions <code>30% - 50% - 20%</code>.</p>
<p>In the function, we need to get these headers back.</p>
<p>OpenFaaS comprehensively documents this: <a href="https://github.com/openfaas/faas/tree/master/watchdog?ref=blog.jmkhael.io#working-with-http-headers">Reference documentation for Function Watchdog</a></p>
<blockquote>
<p>Headers and other request information are injected into environmental variables in the following format: The <code>X-Style-Name</code> header becomes available as <code>Http_X_Style_Name</code>.</p>
</blockquote>
<pre><code>style_name = os.environ.get(&apos;Http_X_Style_Name&apos;, &apos;varied&apos;)
style_index = os.environ.get(&apos;Http_X_Style_Index&apos;, &apos;1&apos;)
which_styles = os.environ.get(&apos;Http_X_Which_Styles&apos;, &quot;{%s:1}&quot; % style_index)
</code></pre>
<p>Then it is a matter of calling the correct model with the correct parameters in the function. Most of the code comes from Magenta&apos;s repository, so make sure to check that out.</p>
<pre><code>if style_name == &apos;monet&apos;:
    FLAGS.num_styles = 10
    FLAGS.checkpoint = &quot;/magenta-models/multistyle-pastiche-generator-monet.ckpt&quot;
    FLAGS.input_image = input_image_name
    FLAGS.which_styles = which_styles
    FLAGS.output_dir = &quot;out_content.jpg&quot;
    FLAGS.output_basename = &quot;monet_styles&quot;
  elif style_name == &apos;varied&apos;:
    FLAGS.num_styles = 32
    FLAGS.checkpoint = &quot;/magenta-models/multistyle-pastiche-generator-varied.ckpt&quot;
    FLAGS.input_image = input_image_name
    FLAGS.which_styles = which_styles
    FLAGS.output_dir = &quot;out_content.jpg&quot;
    FLAGS.output_basename = &quot;varied_styles&quot;
  else:
    raise ValueError(&apos;Style %s is not supported. Accepted values are &quot;monet&quot; or &quot;varied&quot;&apos; % style_name)
</code></pre>
<h5 id="styletransferexample">Style transfer example</h5>
<p>If you want to try my repository locally:</p>
<pre><code>git clone https://github.com/jmkhael/faas-artist
cd faas-artist
faas-cli build -f artist.yml
faas-cli deploy -f artist.yml
</code></pre>
<pre><code>curl -X POST -H X-style-name:varied -H X-style-index:24 \
  --data-binary @artist/input/vespa-faas.jpg \
  &quot;http://localhost:8080/function/artist&quot; &gt; styled/vespa-faas-varied-24.jpg
</code></pre>
<p>or use the helper script:</p>
<p>usage:</p>
<pre><code>./pastiche.sh path_to_image_file style style_index
</code></pre>
<p>style can be monet or varied. style_index from 0 to 9 for monet, and from 0 to 30 for varied.</p>
<blockquote>
<p>try them all, and see what you like!</p>
</blockquote>
<pre><code>./pastiche.sh artist/input/tree.jpg varied 24
./pastiche.sh artist/input/tree.jpg monet 2
</code></pre>
<h5 id="multistyletransferexample">Multi-style transfer example</h5>
<p>We can also apply a multi-style, blending several styles of a given model together, based on weights. e.g.: <code>{1:0.3, 10:0.5, 24:0.2}</code> to tell the artist to use style 1, style 10 and style 24 in the proportions <code>30% - 50% - 20%</code>.</p>
<pre><code>curl -X POST -H X-style-name:varied -H X-which-styles:&apos;{1:0.2,10:0.3,24:0.5}&apos; \
  --data-binary @artist/input/faas-community.jpg \
  &quot;http://localhost:8080/function/artist&quot; &gt; styled/faas-community-varied-1-10-24.jpg
</code></pre>
<p><strong>Original</strong><br>
<img src="https://blog.jmkhael.io/content/images/2017/11/tuscany.jpg" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<p><strong>style-transfer (varied, 1)</strong><br>
<img src="https://blog.jmkhael.io/content/images/2017/11/varied_1_tuscany.jpg" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<p><strong>multi-style-transfer (varied, {1:0.2,10:0.3,24:0.5})</strong><br>
<img src="https://blog.jmkhael.io/content/images/2017/11/tuscany-varied-1-10-24.jpg" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<p><strong>multi-style-transfer (varied, {1:0.2,10:0.7,24:0.1})</strong><br>
<img src="https://blog.jmkhael.io/content/images/2017/11/tuscany-varied-1-10-24_20_70_10.jpg" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
<p>You can visit the repository for more instructions of how to run multi-style transfer.</p>
<h2 id="whattodonext">What to do next?</h2>
<p>You can experiment with all this, and drop me a message if you create something nice!</p>
<blockquote>
<p>If you like what we&apos;ve built in this post, star my repository to show support: <a href="https://github.com/jmkhael/faas-artist?ref=blog.jmkhael.io">https://github.com/jmkhael/faas-artist</a></p>
</blockquote>
<blockquote>
<p>Go star the OpenFaaS project - <a href="https://github.com/openfaas/faas?ref=blog.jmkhael.io">https://github.com/openfaas/faas</a> and be part of it&apos;s vibrant community!</p>
</blockquote>
<p>If you&apos;d like to join OpenFaaS community Slack channel to chat with me or other contributors or get some help - then send a Tweet to <a href="https://twitter.com/alexellisuk/?ref=blog.jmkhael.io">@alexellisuk</a> or email <a href="alex@openfaas.com">alex@openfaas.com</a>.</p>
<blockquote>
<p>Join and add your photo in there!<br>
<img src="https://blog.jmkhael.io/content/images/2017/11/faas-community-varied-6.jpg" alt="Unleash the Artist within you with Docker, Tensorflow and OpenFaaS" loading="lazy"></p>
</blockquote>
<p>Also, make sure to visit Magenta&apos;s <a href="https://magenta.tensorflow.org/?ref=blog.jmkhael.io">website</a> and <a href="https://github.com/tensorflow/magenta?ref=blog.jmkhael.io">repository</a>.</p>
<h2 id="references">References</h2>
<p>I&apos;ve used the below references to be able to generate most of this blog or code.<br>
Go visit each if you need more detail.</p>
<ol>
<li><a href="https://arxiv.org/abs/1610.07629?ref=blog.jmkhael.io">&#x201C;A Learned Representation for Artistic Style&#x201D;</a></li>
<li><a href="https://research.googleblog.com/2016/10/supercharging-style-transfer.html?ref=blog.jmkhael.io">https://research.googleblog.com/2016/10/supercharging-style-transfer.html</a></li>
<li><a href="https://magenta.tensorflow.org/2016/11/01/multistyle-pastiche-generator?ref=blog.jmkhael.io">https://magenta.tensorflow.org/2016/11/01/multistyle-pastiche-generator</a></li>
<li><a href="https://www.youtube.com/watch?v=WHmp26bh0tI&amp;ref=blog.jmkhael.io">https://www.youtube.com/watch?v=WHmp26bh0tI</a></li>
<li><a href="https://github.com/tensorflow/magenta/blob/master/magenta/models/arbitrary_image_stylization/README.md?ref=blog.jmkhael.io">magenta/arbitrary_image_stylization</a></li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Create your own DownNotifier with OpenFaaS]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I went to a three weeks holiday during august, and I was happy to see that my blog (hosted on an old Raspberry Pi 1) kept working the whole time!</p>
<p>Call it good or bad luck, but on the day I returned my blog just stopped working.</p>
<p>I discovered it</p>]]></description><link>https://blog.jmkhael.io/downnotifier-site-pinger/</link><guid isPermaLink="false">653d5697cf37c50001d2406a</guid><category><![CDATA[serverless]]></category><category><![CDATA[openfaas]]></category><category><![CDATA[downnotifier]]></category><category><![CDATA[slack]]></category><category><![CDATA[faas-cli]]></category><category><![CDATA[botkit]]></category><category><![CDATA[rxjs]]></category><category><![CDATA[docker]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Fri, 22 Sep 2017 12:18:01 GMT</pubDate><media:content url="https://blog.jmkhael.io/content/images/2020/01/down_notifier-diagram-2.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.jmkhael.io/content/images/2020/01/down_notifier-diagram-2.png" alt="Create your own DownNotifier with OpenFaaS"><p>I went to a three weeks holiday during august, and I was happy to see that my blog (hosted on an old Raspberry Pi 1) kept working the whole time!</p>
<p>Call it good or bad luck, but on the day I returned my blog just stopped working.</p>
<p>I discovered it by chance, while I was playing with ansible and inadvertently triggered an <code>uptime</code> command on the Raspberry Pi hosting the blog. It just hang endlessly.</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/09/its-fine.jpg" alt="Create your own DownNotifier with OpenFaaS" loading="lazy"></p>
<p>All I had setup back then, was a free alert on <a href="https://www.downnotifier.com/?ref=blog.jmkhael.io">https://www.downnotifier.com/</a><br>
I knew that this isn&apos;t enough and I had to do something.</p>
<blockquote>
<p>DownNotifier sends a free alert when your website is down</p>
</blockquote>
<p>The kind of alerts you get are mail and SMS. You need to buy credits for SMS to work. Free means that all you get is an email when DownNotifier see that your site is down.</p>
<blockquote>
<p>I need a better way to monitor my blog - JM</p>
</blockquote>
<h3 id="whatwewillbuild">What we will build</h3>
<p>Using <a href="https://www.docker.com/?ref=blog.jmkhael.io">Docker</a>, <a href="https://www.openfaas.com/?ref=blog.jmkhael.io">OpenFaaS</a> and a bit of typing, this is what I ended up with in a matter of an hour:</p>
<p>In the top section you can find logs of an OpenFaaS function, the brain of all this, in the bottom section I invoke this function on an inexistant site, and on the right you can see an incoming message to Slack with the site down information!</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/09/down-notifier-out.gif" alt="Create your own DownNotifier with OpenFaaS" loading="lazy"></p>
<h3 id="problemandsolution">Problem and solution</h3>
<p>The problem I wanted to solve, can be simply formulated as:</p>
<p><strong>I need to be notified in under 15 seconds if my blog goes down.</strong><br>
The notification medium is Slack. I want to see the observed error from the client side.</p>
<p>I <s>wanted</s> needed to write something in a matter of an hour, so I feel a bit safer, then make it better later on.</p>
<p>The idea I had in mind is very simple:</p>
<ol>
<li>Schedule a regular ping to the blog</li>
<li>If everything is ok, say nothing on Slack</li>
<li>If it fails, send a message to a Slack channel dedicated to this (#blog)</li>
</ol>
<p>But of course I didn&apos;t want to write a single script to do that! I wanted the solution to remain composable, or to quote Docker&#x2019;s CTO - Solomon Hykes:</p>
<blockquote>
<p>&quot;batteries included, but replaceable&quot;</p>
</blockquote>
<p>So here comes my solution using serverless functions to allow a fast, scalable and modular design. We&#x2019;re going to use the OpenFaaS serverless framework for Docker and Kubernetes.</p>
<h2 id="whyisopenfaasrightforserverless">Why is OpenFaaS right for Serverless?</h2>
<p>With OpenFaaS you can go serverless, without any vendor lock-in.</p>
<p>Some of the nice features of OpenFaaS include:</p>
<ul>
<li>It runs on existing hardware or public/private cloud - Kubernetes or Docker Swarm</li>
<li>It&#x2019;s easy to use and has a built-in UI and one-click deployment</li>
<li>The CLI takes you step-by-step, from scaffolding new functions to deploying them on your cluster</li>
<li>It comes with bells and whistles such as auto-scaling with respect to demand increase and alerting/monitoring...</li>
</ul>
<p>but the reason #1 remains the same:</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Reason number 1 why I love contributing to <a href="https://twitter.com/open_faas?ref=blog.jmkhael.io">@open_faas</a>: the team behind it has great skills and is very helpful</p>&#x2014; Johnny Mkhael (@jmkhael) <a href="https://twitter.com/jmkhael/status/902089475152629760?ref=blog.jmkhael.io">August 28, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><img src="https://camo.githubusercontent.com/cf01eefb5b6905f3774376d6d1ed55b8f052d211/68747470733a2f2f626c6f672e616c6578656c6c69732e696f2f636f6e74656e742f696d616765732f323031372f30382f666161735f736964652e706e67" alt="Create your own DownNotifier with OpenFaaS" loading="lazy"></p>
<h1 id="buthow">But, How?</h1>
<p>In order to implement the above steps, I though of creating 3 functions: one that pings, one that send to slack and the last one, the brain, coordinating all of this.</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/09/down_notifier-diagram-2.png" alt="Create your own DownNotifier with OpenFaaS" loading="lazy"></p>
<ul>
<li><code>url_ping_node</code>: this function is a rewrite of url_ping but in node. It basically pings a site and returns a json with error details in case it fails. It also uses <a href="http://reactivex.io/rxjs/?ref=blog.jmkhael.io">RxJS</a>, reactive model for composing asynchronous and event-based programs by using observable sequences. I will need this to retry/timeout later on.</li>
<li><code>slack_it</code>: this function sends a message to a slack channel<br>
It uses <a href="https://www.botkit.ai/?ref=blog.jmkhael.io">Botkit</a>. It needs a token to access the Slack team. By default it will post to a #blog channel.</li>
<li><code>down_notifier</code>: this is the top level function or <strong>the brain</strong>. It <strong>calls other functions</strong>: first <code>url_ping_node</code> and then decides to pipe a message to <code>slack_it</code> if the ping fails or not.</li>
</ul>
<p>and basically, all what remains is to schedule a recurring call to the <code>down_notifier</code>. (This part is still hackish)</p>
<p><strong>Note</strong></p>
<p>You can find all the code in the accompanying GitHub repository here: <a href="https://github.com/jmkhael/blog-pinger?ref=blog.jmkhael.io">https://github.com/jmkhael/blog-pinger</a>, but be sure to read along, as I&apos;ll highlight the most relevant sections.</p>
<h2 id="implementation">Implementation</h2>
<p>Before starting to write our functions, let&apos;s install <code>faas-cli</code> which is a very nice CLI to <code>list</code>, create <code>new</code>, <code>build</code>, <code>deploy</code>, <code>invoke</code>, <code>push</code> and <code>remove</code> functions to list a few.</p>
<blockquote>
<p>It is the Official CLI for the OpenFaaS Serverless framework - <a href="https://github.com/alexellis/faas-cli?ref=blog.jmkhael.io">GitHub repo</a></p>
</blockquote>
<h3 id="prereqs">Pre-reqs</h3>
<p>Get the <code>faas-cli</code>, if you haven&apos;t yet. You really have to if you want to be productive!<br>
The easiest way to install the <code>faas-cli</code> is through <code>curl</code> or <code>brew</code>:</p>
<pre><code>$ curl -sSL https://cli.openfaas.com | sudo sh
</code></pre>
<p>or:</p>
<pre><code>$ brew install faas-cli
</code></pre>
<p>Start <code>faas-cli</code> and be amazed by it&apos;s ascii art and help message:<br>
<img src="https://blog.jmkhael.io/content/images/2017/09/Screenshot-from-2017-09-21-11-29-33.png" alt="Create your own DownNotifier with OpenFaaS" loading="lazy"></p>
<h2 id="scaffold">Scaffold</h2>
<p>Time to create our functions. Let&apos;s use the faas-cli to do so.</p>
<pre><code>faas-cli new --name url_ping_node --lang node
faas-cli new --name down_notifier --lang node
faas-cli new --name slack_it --lang node
rm master.zip
ls
</code></pre>
<p>Have a look at what faas-cli just scaffolded for us:</p>
<pre><code>$ ls
down_notifier  down_notifier.yml  
slack_it  slack_it.yml  template  
url_ping_node  url_ping_node.yml
</code></pre>
<p>Each yml file is basically a specification we can use to configure/build/deploy individual functions.</p>
<p>You can merge them out into a single &apos;stack&apos;.</p>
<pre><code>cat *.yml &gt; samples.yml
</code></pre>
<p>Check out my <a href="https://github.com/jmkhael/blog-pinger/blob/master/samples.yml?ref=blog.jmkhael.io">samples.yml</a> file for an example.</p>
<h2 id="writingthefunctionslogic">Writing the functions logic</h2>
<p>faas-cli prepared pretty much everything!</p>
<p><code>faas-cli</code>, is like Rick, building dedicated robots in no time!<br>
<img src="https://blog.jmkhael.io/content/images/2017/09/butter-robot.jpg" alt="Create your own DownNotifier with OpenFaaS" loading="lazy"></p>
<p>At the time of writing this post, <code>faas-cli</code> don&apos;t know, <em>yet</em>, what&apos;s in our mind. So we have to write the functions logic ourselves...</p>
<p>Below I am highlighting the most important aspects of these functions, but you can always refer to the <a href="https://github.com/jmkhael/blog-pinger?ref=blog.jmkhael.io">github repo</a> for details.</p>
<blockquote>
<p><code>down_notifier</code> is kind of more evolved as it chain several functions together. Make sure to check it&apos;s code.</p>
</blockquote>
<h3 id="url_ping_node"><code>url_ping_node</code></h3>
<p>I won&apos;t detail much of the code here as it doesn&apos;t do a lot besides what will be covered below.</p>
<p>This function will connect to a URL over HTTP and return the status code, or return the error encountered.</p>
<pre><code>$ echo &apos;{&quot;url&quot;:&quot;http://jmkhael.io/&quot;}&apos; \
| faas-cli invoke --name url_ping_node

{&quot;url&quot;:&quot;http://jmkhael.io/&quot;,&quot;status&quot;:&quot;ok&quot;,&quot;status_code&quot;:200}

$ echo &apos;{&quot;url&quot;:&quot;http://jmkhael.no/&quot;}&apos; \
| faas-cli invoke --name url_ping_node 
{
   &quot;url&quot;:&quot;http://jmkhael.no/&quot;,
   &quot;status&quot;:&quot;nok&quot;,
   &quot;error&quot;:{
         &quot;code&quot;:&quot;ENOTFOUND&quot;,
         &quot;errno&quot;:&quot;ENOTFOUND&quot;,
         &quot;syscall&quot;:&quot;getaddrinfo&quot;,
         &quot;hostname&quot;:&quot;jmkhael.no&quot;,
         &quot;host&quot;:&quot;jmkhael.no&quot;,
         &quot;port&quot;:80
   }
}
</code></pre>
<p>Note that you can do the same with <code>curl</code> if you like. But using faas-cli is more elegant as we saw above:</p>
<pre><code>$ curl -d &apos;{&quot;url&quot;:&quot;http://jmkhael.io/&quot;}&apos; \
http://localhost:8080/function/url_ping_node

$ curl -d &apos;{&quot;url&quot;:&quot;http://jmkhael.no/&quot;}&apos; \
http://localhost:8080/function/url_ping_node
</code></pre>
<h3 id="slack_it"><code>slack_it</code></h3>
<p>This function mission in life is to send a message to a slack channel.</p>
<p>This uses <a href="https://www.botkit.ai/?ref=blog.jmkhael.io">Botkit</a>. By default it will post to a #blog channel.</p>
<p>You need to specify in the environment section a token enabling the function to join your Slack team.</p>
<pre><code>  slack_it:
    lang: node
    handler: ./slack_it
    image: jmkhael/faas-slack
    environment:
      token: &quot;xoxb-insert-your-slack-token-here-but-do-not-add-it-to-github&quot;
</code></pre>
<p>The function will require an input in the form of:</p>
<pre><code>$ curl -d &apos;{&quot;message&quot; : &quot;Anything really&quot;}&apos; \
 http://localhost:8080/function/slack_it
</code></pre>
<p>The message can be any json object. It will be forwarded to the Slack channel.</p>
<pre><code>$ echo &apos;{&quot;message&quot;: {&quot;happy&quot;: &quot;yes, always!&quot;} }&apos; \
| faas-cli invoke --name slack_it
</code></pre>
<h3 id="down_notifier"><code>down_notifier</code></h3>
<p>This function is &quot;the most complicated part&quot; as it orchestrates the whole.<br>
It calls <code>url_ping_node</code> and decides to send a message to <code>slack_it</code> if the ping fails. You can find below the full code (~50 lines)!</p>
<p>The interesting bits, are the calls to <code>post(&apos;http://gateway:8080/function/url_ping_node&apos;)</code> where we call the first function, and then pipe the result to <code>slack_it</code> if the status is &quot;nok&quot;.</p>
<pre><code>&apos;use strict&apos;

const RxHttpRequest = require(&apos;rx-http-request&apos;).RxHttpRequest;
var Rx = require(&apos;rxjs/Rx&apos;);

function down_notifier(url) {
  return RxHttpRequest.post(&apos;http://gateway:8080/function/url_ping_node&apos;, {
      body : {
        url: url
      },
      json: true
    })
    .map(r =&gt; r.body)
    .map(r =&gt; {
      //console.log(&quot;parsed json from url_ping: &quot; + r.status);
      if(r.status !== &quot;ok&quot;) {
        return RxHttpRequest.post(&apos;http://gateway:8080/function/slack_it&apos;, {
            body: r,
            json: true
        })
        .map(r =&gt; r.body);
        // &quot;ping failed - told slack&quot;
      } else {
        return Rx.Observable.of(&quot;all ok - slack not informed&quot;);
      }
    });
}

module.exports = (content, callback) =&gt; {
    //console.log(&quot;Slackin: &quot; + content);
    let req = JSON.parse(content);

    down_notifier(req.url).subscribe(
        (x) =&gt; {
          x.subscribe(r =&gt; {
            let res = {
              &quot;DownNotifier&quot; : &quot;v1&quot;,
              &quot;request&quot; : req,
              &quot;response&quot;: r
            };

            callback(null, JSON.stringify(res));
          });
        },
        (err) =&gt; {
            console.log(&apos;Error: &apos; + err);
        },
        () =&gt; {
            //console.log(&apos;Completed&apos;);
        });
};
</code></pre>
<h3 id="buildanddeploy">Build and deploy</h3>
<p>Building our functions is as easy as doing:</p>
<pre><code>$ faas-cli -action build -f ./samples.yml
</code></pre>
<p>faas-cli is getting better everyday thanks to the great contributions of the community!<br>
e.g. do <code>faas-cli build --parallel 4</code> for instance to make things quicker and <code>faas-cli build --filter=name_of_single_function</code> to build just that one.</p>
<p>In order to deploy, you just issue the command:</p>
<pre><code>$ faas-cli -action deploy -f ./samples.yml
</code></pre>
<p>To stay within Dockerland, I am currently using <a href="https://cron.dockerflow.com/?ref=blog.jmkhael.io">docker-flow-cron</a> to ping the <code>down_notifer</code> function at regular intervals. I&apos;d like to replace this part but something more native to OpenFaaS.</p>
<p>My <code>deploy.sh</code> script basically deploys the faas functions we just wrote, and docker-flow-cron stuff. It can be simplified later on.</p>
<h1 id="whatcanbemadebetter">What can be made better?</h1>
<p>Let&apos;s start by saying that I did this in a matter of an hour or two tops. It took more time to write this blog than to code this!</p>
<p>I wanted something functioning. I didn&apos;t have time to nitpick.</p>
<p>Given time, I would like to:</p>
<ul>
<li>Replace the cron logic with a native OpenFaaS one: wait for or contribute back a faas-cron or a faas-scheduler.</li>
<li>Make the deployment better: now I am dealing with <code>docker stack deploy</code>, <code>docker service create</code> and <code>faas-cli deploy</code>. I need an easier way when my stack is mixed.</li>
<li>Check a list of pages, not just the home page</li>
<li>Setup prometheus as well explained by Alex, <a href="https://blog.alexellis.io/prometheus-monitoring/?ref=blog.jmkhael.io">here</a> and <a href="https://blog.alexellis.io/prometheus-nodeexporter-rpi/?ref=blog.jmkhael.io">there</a>, and send alerts to slack or wherever</li>
<li>Use prometheus alertmanager, which is already part of OpenFaaS stack</li>
<li>Refactor and move some of these function to faas-and-furious organization</li>
</ul>
<h1 id="wheretogonext">Where to go next?</h1>
<p>Things you can do next:</p>
<ul>
<li>Play with this/propose pull requests</li>
<li>Star my repository if you want to show support</li>
<li>Checkout OpenFaaS and deploy your first function</li>
<li>Check OpenFaaS samples on <a href="https://github.com/faas-and-furious?ref=blog.jmkhael.io">faas-and-furious</a></li>
</ul>
<p>You can even contribute to OpenFaaS as an active community that welcomes contributions, if you&#x2019;d like to get involved head over to:</p>
<ul>
<li>OpenFaaS or/and faas-cli</li>
<li>Samples on faas-and-furious. a function like <strong>faas-cron</strong> would be nice :-)</li>
</ul>
<blockquote>
<p>Show your support by giving us a <strong>Star</strong> on the project&apos;s <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">GitHub</a>.</p>
</blockquote>
<blockquote>
<p>If you&apos;d like to join the amazing OpenFaaS community Slack channel to chat with contributors or get some help - then send a Tweet to <a href="https://twitter.com/openfaas?ref=blog.jmkhael.io">@openfaas</a>, <a href="https://twitter.com/alexellisuk?ref=blog.jmkhael.io">@alexellisuk</a> or email <a href="mailto:alex@openfaas.com">alex@openfaas.com</a>.</p>
</blockquote>
<h2 id="youmightalsolike">You might also like:</h2>
<ul>
<li><a href="https://blog.jmkhael.io/kittens-vs-tarsiers-an-introduction-to-serverless-machine-learning/">Kittens vs Tarsiers - an introduction to serverless machine learning</a></li>
<li><a href="https://blog.jmkhael.io/create-a-serverless-ascii-banner-with-faas/">Old and new - ASCII art and serverless</a></li>
<li><a href="code-a-morse-serverless-function-in-quick-basic-with-faas-and-docker/">Create a Morse Code serverless FaaS function in Quick Basic!</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Kittens vs Tarsiers - an introduction to serverless machine learning]]></title><description><![CDATA[In this blog post we will develop a serverless function to identify **Doppelgängers**.
We will use FaaS, Docker and TensorFlow for image recognition.]]></description><link>https://blog.jmkhael.io/kittens-vs-tarsiers-an-introduction-to-serverless-machine-learning/</link><guid isPermaLink="false">653d5697cf37c50001d24064</guid><category><![CDATA[docker]]></category><category><![CDATA[faas]]></category><category><![CDATA[serverless]]></category><category><![CDATA[tensorflow]]></category><category><![CDATA[machine-learning]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Mon, 24 Jul 2017 07:49:11 GMT</pubDate><media:content url="https://blog.jmkhael.io/content/images/2017/07/f70375a4541dc8d1863525cd7d8ad2aa.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.jmkhael.io/content/images/2017/07/f70375a4541dc8d1863525cd7d8ad2aa.jpg" alt="Kittens vs Tarsiers - an introduction to serverless machine learning"><p>In this first part of this blog post series we will develop a serverless function to identify <strong>Doppelg&#xE4;ngers</strong>.<br>
<img src="https://blog.jmkhael.io/content/images/2017/07/tarsier-cat.jpg" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<p>We will be using Functions as a Service (<a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a>), which is a framework for building serverless functions with Docker, TensorFlow for image recognition. Needless to say, we will be using Docker.</p>
<p>Throw any url at it, and the function will tell you what it (thinks it) sees.</p>
<p>How does it tell you what it thinks? It runs an image classification with <strong>Inception</strong> provided by Tensorflow. Inception was trained on <a href="http://www.image-net.org/?ref=blog.jmkhael.io">ImageNet</a> image database.</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/07/Screenshot-from-2017-07-19-22-25-31.png" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<pre><code>tabby, tabby cat (score = 0.67659)
tiger cat (score = 0.22639)
lynx, catamount (score = 0.02460)
Egyptian cat (score = 0.01052)
Persian cat (score = 0.00236)
</code></pre>
<p><img src="https://blog.jmkhael.io/content/images/2017/07/cat-1508613_960_720.jpg" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<blockquote>
<p>Note that the function will be able to identify other animals and objects</p>
</blockquote>
<pre><code>Boston bull, Boston terrier (score = 0.17929)
king penguin, Aptenodytes patagonica (score = 0.16913)
French bulldog (score = 0.02329)
toy terrier (score = 0.00909)
Italian greyhound (score = 0.00524)
</code></pre>
<p><img src="https://blog.jmkhael.io/content/images/2017/07/penguin-dog.jpg" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<p>But let&apos;s face it, tarsier and cats are the REAL Doppelg&#xE4;ngers!</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/07/tarsier-cat.jpg" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<blockquote>
<p>Will we be able to split them apart?</p>
</blockquote>
<h2 id="demo">Demo</h2>
<p>Let&apos;s start with a demo, and set up FaaS so we can test out the doppelgangers and see what the function makes of it.</p>
<p>You can try this out in Play With Docker using the PWD button, how that works is by downloading a Docker Compose Stack file and all the images that are needed for FaaS and for the machine learning function (which we will write).</p>
<p>If you are already familiar with <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a> and cannot wait to play with this, head over to PWD and give it a round of tests</p>
<p>You can <a href="http://play-with-docker.com/?stack=https%3A%2F%2Fraw.githubusercontent.com%2Fjmkhael%2Ffaas-tensorflow%2Fmaster%2Fdocker-compose.yml&amp;stack_name=func&amp;ref=blog.jmkhael.io"><img src="https://cdn.rawgit.com/play-with-docker/stacks/cff22438/assets/images/button.png" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></a></p>
<blockquote>
<p>Wait a while until the Tensorflow Docker image extract. Be patient...</p>
</blockquote>
<p>then click the blue badge at the top to open FaaS UI:</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/07/Screenshot-from-2017-07-19-23-06-05.png" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<p>then click on the tensorflow entry on the left<br>
<img src="https://blog.jmkhael.io/content/images/2017/07/Screenshot-from-2017-07-19-23-06-47.png" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<p>type or paste in the <em>Request body</em> field any url pointing to an image and click <strong>INVOKE</strong>.</p>
<p>Test this on the internet celebrity Hipster Cat.<br>
<img src="https://blog.jmkhael.io/content/images/2017/07/hipster-cat2.jpg" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<p>It got identified as a tabby cat with an 23% confidence level. It spotted a carton, a bow tie and maybe a welcome mat.</p>
<pre><code>tabby, tabby cat (score = 0.23278)
Persian cat (score = 0.09450)
doormat, welcome mat (score = 0.05816)
bow tie, bow-tie, bowtie (score = 0.04336)
carton (score = 0.03877)
</code></pre>
<p>Let&apos;s test a harder one:<br>
<img src="https://blog.jmkhael.io/content/images/2017/07/penguin-dog.jpg" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<p><img src="https://blog.jmkhael.io/content/images/2017/07/Screenshot-from-2017-07-20-14-54-22.png" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<p>A boston bull and a king penguin are spotted with high confidence level (16.9% and 17.9% respectively).</p>
<pre><code>Boston bull, Boston terrier (score = 0.17929)
king penguin, Aptenodytes patagonica (score = 0.16913)
French bulldog (score = 0.02329)
toy terrier (score = 0.00909)
Italian greyhound (score = 0.00524)
</code></pre>
<p>You can also use curl if you prefer:<br>
(this url points to another cat photo)</p>
<pre><code>curl http://localhost:8080/function/func_tensorflow -d \
       &apos;https://cdn.pixabay.com/photo/2016/07/10/21/47/cat-1508613_960_720.jpg&apos;
</code></pre>
<p>You can find in my <a href="https://github.com/jmkhael/faas-tensorflow?ref=blog.jmkhael.io">github repository</a> all the code and simple instructions to set it up and test it locally too - but I advise you to read along as there will be a trick or two (one of them to go async :-) )</p>
<p>A big thank you to Alex Ellis (<a href="https://twitter.com/alexellisuk?ref=blog.jmkhael.io">@alexellisuk</a>) for creating this <a href="https://blog.alexellis.io/blog-community-inspiration/?ref=blog.jmkhael.io">community</a> and his continuous support!</p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">This is what open-source <a href="https://twitter.com/hashtag/community?src=hash&amp;ref=blog.jmkhael.io">#community</a> looks like - logging into Slack to see an awesome <a href="https://twitter.com/Docker?ref=blog.jmkhael.io">@Docker</a> + FaaS + TensorFlow hack by <a href="https://twitter.com/jmkhael?ref=blog.jmkhael.io">@jmkhael</a> &#x1F920; <a href="https://t.co/4cAGsoWdVA?ref=blog.jmkhael.io">pic.twitter.com/4cAGsoWdVA</a></p>&#x2014; Alex Ellis (@alexellisuk) <a href="https://twitter.com/alexellisuk/status/887392646104309760?ref=blog.jmkhael.io">July 18, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<h2 id="ingredients">Ingredients</h2>
<h3 id="serverless">Serverless</h3>
<p>Not familiar with what Serverless can do? Read my guide <a href="https://blog.jmkhael.io/serverless-and-on-my-own-servers/">here</a>.</p>
<p>We will be using <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a>, which is a framework for building serverless functions with Docker.</p>
<blockquote>
<p>That means that FaaS can run on a Docker Swarm! sweet!</p>
</blockquote>
<h3 id="tensorflow">TensorFlow</h3>
<p>We will use TensorFlow for image recognition. But first, let&apos;s define TensorFlow and see what it can do for us.</p>
<h4 id="abouttensorflow">About TensorFlow</h4>
<p>The <a href="https://www.tensorflow.org/?ref=blog.jmkhael.io">Tensorflow site</a> define <strong>TensorFlow</strong> as such:</p>
<blockquote>
<p>TensorFlow&#x2122; is an open source software library for numerical computation using data flow graphs. Nodes in the graph represent mathematical operations, while the graph edges represent the multidimensional data arrays (tensors) communicated between them. The flexible architecture allows you to deploy computation to one or more CPUs or GPUs in a desktop, server, or mobile device with a single API.</p>
</blockquote>
<p>In easier words, you write your code once, and it can execute on a CPU, GPU and now even on a <a href="https://en.wikipedia.org/wiki/Tensor_processing_unit?ref=blog.jmkhael.io">TPU</a>!</p>
<h3 id="wherecanweruntensorflow">Where can we run TensorFlow?</h3>
<p><img src="https://blog.jmkhael.io/content/images/2017/07/Screenshot_20170719-150042.png" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<blockquote>
<p>Imagine that you can run your code on your local machine, phone, raspberry pi and even on GCP - CLOUD TPU -  introduced by Google <a href="https://www.blog.google/topics/google-cloud/google-cloud-offer-tpus-machine-learning/?ref=blog.jmkhael.io">here</a>.</p>
</blockquote>
<p><img src="https://storage.googleapis.com/gweb-uniblog-publish-prod/images/tpu-v2-1.width-1000.png" alt="Kittens vs Tarsiers - an introduction to serverless machine learning" loading="lazy"></p>
<h3 id="whatcanwebuildwithtensorflow">What can we build with TensorFlow?</h3>
<p>Nothing better than to browse through <a href="https://github.com/jtoy/awesome-tensorflow?ref=blog.jmkhael.io">Awesome TensorFlow</a> to get some ideas.</p>
<p>For convenience, I&apos;ll list a few things which one can do with TensorFlow:</p>
<ul>
<li>build a smart, conversational chatbot</li>
<li>translate between the writings of Shakespeare and modern English</li>
<li>generate art, music or handwriting...</li>
<li>teach a bot to play a game (Deep-Q learning)</li>
<li>search, filter, and describe videos based on objects, places that appear in them</li>
<li>lip reading</li>
<li>real-time object detection</li>
<li>image recognition...</li>
</ul>
<blockquote>
<p>and so much more!</p>
</blockquote>
<h2 id="next">Next</h2>
<blockquote>
<p>Before going further, check out <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a> and Star the project!<br>
You can start building your serverless function and have it featured in the community Alex built! Pull requests are welcome!</p>
</blockquote>
<p>Next we will dive deeper. We will be building a Serverless FaaS function for deep learning in 10 minutes.</p>
<p>In future blog post we will do one of the below:</p>
<ul>
<li>Add an overlay of the tags on the image and store that it an s3 bucket (use <a href="http://www.pythonware.com/products/pil/?ref=blog.jmkhael.io">PIL</a>)</li>
<li>do the same thing with FaaS and Tensorflow but on a Raspberry Pi 3 with the same code but on pi cam</li>
<li>go asynchronous, scale the workers and get back the results</li>
<li>Execute the same thing but on a GPU/(later on a TPU)</li>
<li>train the model so it recognize other things - maybe to distinguish Darth Vader from any father??</li>
<li>a slack integration that will classify images shared?</li>
</ul>
<p><strong>Tell me which one you&apos;d like to see next?</strong></p>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">&quot;FaaS&quot; and Furious - building Serverless apps with Docker just got even easier <a href="https://t.co/FewLLlNHDB?ref=blog.jmkhael.io">https://t.co/FewLLlNHDB</a> <a href="https://twitter.com/Docker?ref=blog.jmkhael.io">@Docker</a> <a href="https://twitter.com/hashtag/faas?src=hash&amp;ref=blog.jmkhael.io">#faas</a> <a href="https://twitter.com/hashtag/serverless?src=hash&amp;ref=blog.jmkhael.io">#serverless</a> <a href="https://t.co/1yfpseqXVp?ref=blog.jmkhael.io">pic.twitter.com/1yfpseqXVp</a></p>&#x2014; Alex Ellis (@alexellisuk) <a href="https://twitter.com/alexellisuk/status/879797541092696064?ref=blog.jmkhael.io">June 27, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script><!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Old and new - ASCII art and serverless]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In this post, we will build a <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a> function for creating Ascii banners without writing a single line of code. Why? Well because Ascii banners are nice!</p>
<h1 id="waitwesaidnocode">Wait! We said no code!</h1>
<p>For that, we will use, Figlet:</p>
<blockquote>
<p>FIGlet is a program for making large letters out of ordinary text</p></blockquote>]]></description><link>https://blog.jmkhael.io/create-a-serverless-ascii-banner-with-faas/</link><guid isPermaLink="false">653d5697cf37c50001d24062</guid><category><![CDATA[serverless]]></category><category><![CDATA[faas]]></category><category><![CDATA[docker]]></category><category><![CDATA[docker-swarm]]></category><category><![CDATA[play-with-docker]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Mon, 26 Jun 2017 12:06:17 GMT</pubDate><media:content url="https://blog.jmkhael.io/content/images/2020/01/faas-figlet-output.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.jmkhael.io/content/images/2020/01/faas-figlet-output.png" alt="Old and new - ASCII art and serverless"><p>In this post, we will build a <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a> function for creating Ascii banners without writing a single line of code. Why? Well because Ascii banners are nice!</p>
<h1 id="waitwesaidnocode">Wait! We said no code!</h1>
<p>For that, we will use, Figlet:</p>
<blockquote>
<p>FIGlet is a program for making large letters out of ordinary text</p>
</blockquote>
<p>Using <a href="http://www.figlet.org/?ref=blog.jmkhael.io">Figlet</a>, and <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a>, we will create a Function (fka. Lambda), to be able to create banners such as this one:</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/06/faas-figlet-output.png" alt="Old and new - ASCII art and serverless" loading="lazy"></p>
<h2 id="doatestrunonpwdoronaswarm">Do a test run on PWD or on a Swarm</h2>
<p>If you want to see how this would behave, go ahead, and <a href="http://play-with-docker.com/?stack=https%3A%2F%2Fraw.githubusercontent.com%2Fjmkhael%2Ffaas-figlet%2Fmaster%2Fdocker-compose.yml&amp;stack_name=func&amp;ref=blog.jmkhael.io"><img src="https://cdn.rawgit.com/play-with-docker/stacks/cff22438/assets/images/button.png" alt="Old and new - ASCII art and serverless" loading="lazy"></a></p>
<p>Once the stack is ready, just call:</p>
<pre><code>curl http://localhost:8080/function/func_figlet -d &apos;Hello, FaaS, world&apos;
</code></pre>
<p>and see the magic!</p>
<p>You can also try this out on your laptop if you have Docker installed already<br>
by deploying the <a href="https://github.com/jmkhael/faas-figlet/blob/master/docker-compose.yml?ref=blog.jmkhael.io">docker-compose</a> file:</p>
<pre><code>docker swarm init
docker stack deploy -c docker-compose.yml func
</code></pre>
<blockquote>
<p>If this is the first time you are reading about this subject, maybe you should start with this <a href="https://blog.jmkhael.io/serverless-and-on-my-own-servers/">post first</a> or the <a href="http://blog.alexellis.io/functions-as-a-service/?ref=blog.jmkhael.io">post</a> by Docker Captain <a href="https://twitter.com/alexellisuk?lang=en&amp;ref=blog.jmkhael.io">Alex Ellis</a>.</p>
</blockquote>
<h2 id="preparetheimage">Prepare the image</h2>
<p>We can base our image on a latest alpine, add to it figlet, and add FaaS watchdog and specify figlet as the process to execute:</p>
<pre><code>FROM alpine:3.5

RUN apk update &amp;&amp; apk upgrade
RUN apk add figlet

ADD https://github.com/alexellis/faas/releases/download/0.5.6-alpha/fwatchdog /usr/bin
RUN chmod +x /usr/bin/fwatchdog

ENV fprocess=&quot;figlet&quot;
CMD [&quot;fwatchdog&quot;]
</code></pre>
<blockquote>
<p>You can find all the code and scripts accompanying this post here: <a href="https://github.com/jmkhael/faas-figlet?ref=blog.jmkhael.io">https://github.com/jmkhael/faas-figlet</a></p>
</blockquote>
<h2 id="builddeployandtest">Build, deploy and test</h2>
<p>First, let&apos;s build the image above:</p>
<pre><code>docker build -t jmkhael/faas-figlet .
</code></pre>
<p>Now, we are ready to deploy our function.<br>
For that we will be using the <a href="https://github.com/alexellis/faas-cli?ref=blog.jmkhael.io">faas-cli</a>.</p>
<blockquote>
<p>I&apos;ll also give an alternative way to deploy from the shell - you can find the scripts in the github repo</p>
</blockquote>
<h3 id="deploywithfaascli">Deploy with faas-cli</h3>
<blockquote>
<p>This experimental CLI can be used to and deploy functions to FaaS or to build Node.js or Python functions from a templates meaning you just write a handler file (handler.py/handler.js).</p>
</blockquote>
<blockquote>
<p>You define individual functions or a set of of them within a YAML file. This makes the CLI easier to use and means you can use this file to deploy to your FaaS instance.</p>
</blockquote>
<p>In laymen&apos;s term, faas-cli can help you scaffold a function. Supported languages are python and node.js. It can deploy your function from a yml file.</p>
<blockquote>
<p>We will only use faas-cli to deploy our function in this example. for a more in depth introduction to faas-cli, check Alex&apos;s <a href="http://blog.alexellis.io/build-and-deploy-with-faas/?ref=blog.jmkhael.io">post here</a></p>
</blockquote>
<p>First make sure to install faas-cli if you don&apos;t have it yet, like so:</p>
<pre><code>curl -sSL cli.get-faas.com | sudo sh
</code></pre>
<p>As stated, faas-cli supports a YAML file where you can define metadata describing your functions.</p>
<p>Below you can find the yml file for this example:</p>
<pre><code>provider:
  name: faas
  gateway: http://localhost:8080
  network: &quot;func_functions&quot; # this is optional and defaults to func_functions

functions:
  func_figlet:
    image: jmkhael/faas-figlet
    fprocess: figlet
</code></pre>
<p>Now we can use faas-cli to deploy our function:</p>
<pre><code>faas-cli -action=deploy -f faas-figlet.yml 
</code></pre>
<p>if everything went fine, you should see that faas-cli deployed your service and gave you a url where that function resides:</p>
<pre><code>Deploying: func_figlet.
No existing service to remove
200 OK
URL: http://localhost:8080/function/func_figlet
</code></pre>
<p>Let&apos;s try to hit that url with some data:</p>
<pre><code>curl http://localhost:8080/function/func_figlet -d &apos;Hello, FaaS, world&apos;
</code></pre>
<p><img src="https://blog.jmkhael.io/content/images/2017/06/faas-figlet-output.png" alt="Old and new - ASCII art and serverless" loading="lazy"></p>
<p>This is one of the simplest FaaS function you can build without coding!</p>
<h2 id="next">Next</h2>
<p>I am contemplating a build of a GPGPU function on a Swarm of Raspberry Pis maybe using <a href="https://github.com/mn416/QPULib?ref=blog.jmkhael.io">https://github.com/mn416/QPULib</a> or <a href="https://github.com/nineties/py-videocore:?ref=blog.jmkhael.io">https://github.com/nineties/py-videocore:</a></p>
<blockquote>
<p>The Pi contains 12 QPUs in total, each running at 250MHz. That&apos;s a max throughput of 750M vector instructions per second (250M cycles divided by 4 cycles-per-instruction times 12 QPUs). Or: 12B operations per second (750M instructions times 16 vector elements). QPU instructions can in some cases deliver two results at a time, so the Pi&apos;s QPUs are often advertised at 24 GFLOPS.</p>
</blockquote>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>Thanks to <a href="https://twitter.com/alexellisuk?lang=en&amp;ref=blog.jmkhael.io">@Alex Ellis</a> for feedback on the post.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Create a Morse Code serverless FaaS function in Quick Basic!]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h2 id="why">Why?</h2>
<p>Why would anyone sane code using such an old language?</p>
<blockquote>
<p>Why not? - JM</p>
</blockquote>
<p>After my <a href="https://blog.jmkhael.io/serverless-and-on-my-own-servers/">quick dive into FaaS</a>, I was thinking what would be the oldest language I&apos;ve written with and how much time would it take me to wrap it up in a Docker</p>]]></description><link>https://blog.jmkhael.io/code-a-morse-serverless-function-in-quick-basic-with-faas-and-docker/</link><guid isPermaLink="false">653d5697cf37c50001d2405d</guid><category><![CDATA[docker]]></category><category><![CDATA[faas]]></category><category><![CDATA[serverless]]></category><category><![CDATA[qbasic]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Mon, 08 May 2017 19:11:01 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="why">Why?</h2>
<p>Why would anyone sane code using such an old language?</p>
<blockquote>
<p>Why not? - JM</p>
</blockquote>
<p>After my <a href="https://blog.jmkhael.io/serverless-and-on-my-own-servers/">quick dive into FaaS</a>, I was thinking what would be the oldest language I&apos;ve written with and how much time would it take me to wrap it up in a Docker image and drop in a FaaS function?</p>
<blockquote>
<p>Less than an hour</p>
</blockquote>
<p>You can check out the code here:<br>
<a href="https://github.com/jmkhael/faas-qbasic-morse/?ref=blog.jmkhael.io">https://github.com/jmkhael/faas-qbasic-morse/</a></p>
<h2 id="buildinganddeploying">Building and deploying</h2>
<p>Build the Docker image.</p>
<pre><code>docker build . -t jmkhael/faas-qbasic-morse

</code></pre>
<h3 id="shipittofaas">Ship it to FaaS</h3>
<h4 id="eitherviafaascli">Either via faas-cli</h4>
<p>Build the FaaS cli first:</p>
<pre><code>git clone https://github.com/alexellis/faas-cli
cd faas-cli/
go get -d -v
go build

</code></pre>
<p>Then use the cli to ship the newly built image:</p>
<pre><code>./faas-cli -action=deploy \
   -image=jmkhael/faas-qbasic-morse \
   -name=morse \
   -handler=&quot;python handler.py&quot; \
   -lang=python

</code></pre>
<h4 id="alternativelyshipwithcurl">Alternatively, ship with curl</h4>
<p>You can always use curl to deploy the function to FaaS:</p>
<pre><code>curl localhost:8080/system/functions -d &apos;{
   &quot;service&quot;: &quot;morse&quot;,
   &quot;image&quot;: &quot;jmkhael/faas-qbasic-morse&quot;,
   &quot;envProcess&quot;: &quot;python handler.py&quot;,
   &quot;network&quot;: &quot;func_functions&quot;
  }&apos;

</code></pre>
<p>or if you are a UI portal kind of person, navigate to: <a href="http://localhost:8080/?ref=blog.jmkhael.io">http://localhost:8080</a></p>
<h4 id="testthemorsecodeserverlessfunction">Test the Morse Code Serverless Function</h4>
<p>Time to test our function, let&apos;s run it:</p>
<pre><code>curl -X POST http://localhost:8080/function/morse -d &quot;FaaS-inating!&quot;.

</code></pre>
<p>and see it answer in Morse:</p>
<pre><code>  ..-. .- .- ...  .. -. .- - .. -. --.
</code></pre>
<p><img src="https://blog.jmkhael.io/content/images/2017/05/faas-morse.png" alt="morse-faas" loading="lazy"></p>
<p>Now you can talk Morse via QBasic/Faas!</p>
<p>(I&apos;ve based most of my code shamelessly on the repo and adapted it to be able to drop in a QBasic FaaS function <a href="https://github.com/psuter/serverless-qbasic?ref=blog.jmkhael.io">here</a> - it was about going fast anyway)</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA["Serverless"? And on my own servers?!]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>This post will introduce Serverless, then showcase <a href="http://docs.get-faas.com/?ref=blog.jmkhael.io">Functions as a Service - a serverless framework for Docker</a>, winner in the Cool Hacks contest for Dockercon 2017, by Docker Captain <a href="https://twitter.com/alexellisuk?ref=blog.jmkhael.io">@alexellisuk</a>.</p>
<p>In this episode, we will:</p>
<ol start="0">
<li>briefly touch on what Serverless is/means (to me)</li>
<li>test drive FaaS for Docker</li>
<li>test</li></ol>]]></description><link>https://blog.jmkhael.io/serverless-and-on-my-own-servers/</link><guid isPermaLink="false">653d5697cf37c50001d2405c</guid><category><![CDATA[serverless]]></category><category><![CDATA[faas]]></category><category><![CDATA[dockercon]]></category><category><![CDATA[lambda]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Thu, 04 May 2017 16:54:28 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This post will introduce Serverless, then showcase <a href="http://docs.get-faas.com/?ref=blog.jmkhael.io">Functions as a Service - a serverless framework for Docker</a>, winner in the Cool Hacks contest for Dockercon 2017, by Docker Captain <a href="https://twitter.com/alexellisuk?ref=blog.jmkhael.io">@alexellisuk</a>.</p>
<p>In this episode, we will:</p>
<ol start="0">
<li>briefly touch on what Serverless is/means (to me)</li>
<li>test drive FaaS for Docker</li>
<li>test one of the already available functions (demo)</li>
<li>create and deploy a new function</li>
</ol>
<h2 id="whatisserverless">What is &quot;Serverless&quot;?</h2>
<blockquote>
<p>Serverless architectures are internet based systems where the application development does not use the usual server process. Instead they rely solely on a combination of third-party services, client-side logic, and service hosted remote procedure calls (FaaS). - You can read more on <a href="https://martinfowler.com/bliki/Serverless.html?ref=blog.jmkhael.io">Martin Fowler&apos;s bliki</a></p>
</blockquote>
<p><em>Internet based</em> does not mean you cannot host this on your machine!</p>
<h3 id="aneasierdefinition">An easier definition</h3>
<p>In laymen terms, you write the code, usually event driven, and someone else provision the servers, the running environment, and execute your code!<br>
It promises to handle spikes in traffic, scheduling your code as necessary to serve requests. Requests are usually billed per execution rather than per execution time.</p>
<h3 id="whyuseit">Why use it?</h3>
<p>The real incentive to use a Serverless architecture are cost, (if you have non constant or bursty traffic) and the architectural style/programming model (one step closer to a functional world).</p>
<p><a href="https://aws.amazon.com/lambda/?ref=blog.jmkhael.io">AWS Lambda</a>, <a href="https://cloud.google.com/functions/?ref=blog.jmkhael.io">Google Cloud Functions</a>, <a href="https://www.ibm.com/cloud-computing/bluemix/openwhisk?ref=blog.jmkhael.io">IBM OpenWhisk</a> or <a href="https://azure.microsoft.com/en-us/services/functions/?ref=blog.jmkhael.io">Azure Functions</a> are examples of implementation of today&apos;s cloud providers.</p>
<p><strong>There is no free lunch though</strong></p>
<p>Like most things, Serverless comes with it&apos;s set of concerns. but we won&apos;t talk about those for now. (I&apos;ll name just one: testing is harder)</p>
<h2 id="amisnomerreally">A misnomer, really...</h2>
<p>But wait, after all, there are servers! Then why do we call it Serverless?</p>
<blockquote>
<p>should it be Server(less-ops)?</p>
</blockquote>
<p><img src="https://blog.jmkhael.io/content/images/2017/05/serverless-meme.jpg" alt="meme" loading="lazy"></p>
<p>It is just that:</p>
<ul>
<li>we do not have to provision, or operate those servers</li>
<li>we do not have to do the capacity planning for the peak demand</li>
<li>we do not have to handle the autoscaling</li>
<li>we approach a pay as you go model</li>
</ul>
<h2 id="whatcaniuseserverlessfortoday">What can I use Serverless for, today?</h2>
<p>Do you want to build some RESTful APIs to respond to an action, respond with data, or just serve static content, like images or gif?</p>
<p>Maybe you want to create a webhook for when your Github repo gets a star and you want to light up a bulb in your house?</p>
<p>Maybe even spin off your own <a href="https://ifttt.com/?ref=blog.jmkhael.io">IFTTT</a> or <a href="https://zapier.com/?ref=blog.jmkhael.io">Zapier</a>?</p>
<blockquote>
<p>Well, these kind of use cases hit Serverless sweet spot.</p>
</blockquote>
<h3 id="whereitdoesntreallyfityet">Where it doesn&apos;t really fit (yet)</h3>
<ul>
<li>HPC (due to loss of pricing benefits and/or latencies associated with the model)</li>
</ul>
<h2 id="howtogetstartedtoday">How to get started today?</h2>
<p>You might say to yourself, ok this seems like a thing to learn, but I don&apos;t want to spend hours paying while/learning/locked in/.. about consoles of AWS, Azure, GCP or any other.</p>
<p>This is one of the main drives behind FaaS - to make it easy to build and test Serverless architecture on your own hardware. (For the whole background story leading to FaaS, you can read <a href="http://blog.alexellis.io/functions-as-a-service/?ref=blog.jmkhael.io">this post</a> by Alex Ellis)</p>
<p>Let&apos;s go already.</p>
<h3 id="handsonfaas">Hand&apos;s on FaaS</h3>
<p>To <a href="https://github.com/alexellis/faas/blob/master/TestDrive.md?ref=blog.jmkhael.io">test drive</a> FaaS, Alex was nice enough to get you going in a one liner!</p>
<p>All you need to do first is install Docker:</p>
<pre><code>curl -sSL get.docker.com | sh
</code></pre>
<p>(And if you are lazy, head over to <a href="http://play-with-docker.com/?ref=blog.jmkhael.io">http://play-with-docker.com/</a> and click &quot;Add new Instance&quot;. - but this won&apos;t be on your server - unless you deployed play with docker on your machine as per my <a href="https://blog.jmkhael.io/deploying-play-with-docker-com-on-my-machine/">previous post</a>)</p>
<pre><code>docker swarm init &amp;&amp; \
  git clone https://github.com/alexellis/faas &amp;&amp; \
  cd faas &amp;&amp; \
  ./deploy_stack.sh &amp;&amp; \
  docker service ls
</code></pre>
<p>Once all services listed with <code>docker service ls</code> are up and running (all services have at least one replica) :</p>
<pre><code>NAME                MODE                REPLICAS            IMAGE
func_echoit         replicated          1/1                 functions/alpine:health
func_base64         replicated          1/1                 functions/alpine:health
func_markdown       replicated          1/1                 alexellis2/faas-markdownrender:latest
func_nodeinfo       replicated          1/1                 alexellis2/faas-nodeinfo:latest
func_decodebase64   replicated          1/1                 functions/alpine:health
func_wordcount      replicated          1/1                 functions/alpine:health
func_gateway        replicated          1/1                 functions/gateway:0.5.3
func_webhookstash   replicated          1/1                 functions/webhookstash:latest
func_prometheus     replicated          1/1                 functions/prometheus:1.5.2
func_hubstats       replicated          1/1                 alexellis2/faas-dockerhubstats:latest
func_alertmanager   replicated          1/1                 quay.io/prometheus/alertmanager:latest

</code></pre>
<h4 id="firstencounterwithfaas">First encounter with FaaS</h4>
<p>At this point you can start interacting with FaaS.</p>
<p>Navigate to: <a href="http://localhost:8080/?ref=blog.jmkhael.io">http://localhost:8080/</a> in order to see the UI portal of FaaS.</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/05/faas-ui.png" alt="faas-ui" loading="lazy"></p>
<p>This UI reminds me a bit of <a href="https://www.getpostman.com/?ref=blog.jmkhael.io">Postman</a>.</p>
<p>Here you will see a list of functions prepackaged with FaaS, already deployed by the above command, waiting for you to test!</p>
<blockquote>
<p>There is more than meet the eyes in this simple deployment. For instance, here we already have a portable, easy to use, auto-scaling on demand with Prometheus metrics/alerting! and a Gateway... and the ability to add new functions...</p>
</blockquote>
<h4 id="testingaprepackagedfunction">Testing a prepackaged function</h4>
<p>Let&apos;s test two prepackaged functions, one through the UI and the other through the REST interface.</p>
<h5 id="interactingthroughtheui">Interacting through the UI</h5>
<p>Let&apos;s test the wordcount function through the UI. This function expects a text in and will respond with the number of words/letters in that text.</p>
<p>For that, just click on the left <strong>func_wordcount</strong>:</p>
<p>Type anything you like (including the text, anything you like ;)) in the Request body then click <strong>INVOKE</strong>.<br>
You should see the Response body adapt with the number of words/letters and the function&apos;s invocation count increment!</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/05/faas-testdrive-ui.png" alt="faas-testdrive-ui" loading="lazy"></p>
<p>Sweet.</p>
<h5 id="interactingviacurl">Interacting via curl</h5>
<p>Let&apos;s now test the markdown function through the command line. This function expects a markdown text, and will convert it to an html equivalent:</p>
<pre><code>curl -X POST http://localhost:8080/function/func_markdown -d &quot;&gt; This is FaaS in action! - JM&quot;
</code></pre>
<p>and get the html back:</p>
<pre><code>&lt;blockquote&gt;
&lt;p&gt;This is FaaS in action! - JM&lt;/p&gt;
&lt;/blockquote&gt;
</code></pre>
<h4 id="packagingmyownfunction">Packaging my own function</h4>
<p>Ok that&apos;s really nice. But what about adding my own function?</p>
<p>Again, we can do this either through the UI or via the REST API.</p>
<p>Let&apos;s create a function to reverse text given as input...</p>
<p>To do that, I will use an Alpine base image and the <code>rev</code> command.</p>
<p>Click <strong>CREATE NEW FUNCTION</strong> link on the left</p>
<p>and fill the form as per the below:<br>
<img src="https://blog.jmkhael.io/content/images/2017/05/add-function-ui.png" alt="add-function" loading="lazy"></p>
<p>The equivalent to this from the command line:</p>
<pre><code>curl localhost:8080/system/functions -d &apos;{&quot;service&quot;: &quot;esrever&quot;, &quot;image&quot;: &quot;functions/alpine&quot;, &quot;envProcess&quot;: &quot;rev&quot;, &quot;network&quot;: &quot;func_functions&quot;}&apos;
</code></pre>
<p>Or you can also use the new and shiny <a href="https://github.com/alexellis/faas-cli?ref=blog.jmkhael.io">faas-cli</a> to scaffold, build and deploy to FaaS. (comming in next post)</p>
<p>Now, check the UI to see the newly added function:</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/05/reverse-func.png" alt="reverse-func" loading="lazy"></p>
<p>Test it by giving it the service name we used: esrever, so it become reverse.</p>
<p>You can also do that from the command line of course:</p>
<pre><code>curl -X POST http://localhost:8080/function/esrever -d &quot;.emosewA si SaaF###&quot;
</code></pre>
<blockquote>
<h3 id="faasisawesome">FaaS is Awesome.</h3>
</blockquote>
<h1 id="comingupsoon">Coming up soon</h1>
<p>In a future post we will explore how FaaS will behave on my hybrid Swarm of Raspberry Pi, composed of one Zero, few Rpi2 and few Rpi3.</p>
<p>We will also be writing some code in Python, and deploying it to FaaS ... all this using the new and shiny <a href="https://github.com/alexellis/faas-cli?ref=blog.jmkhael.io">faas-cli</a></p>
<p>We may wire an IFTTT webhook or do an image recognition using TensorFlow :)</p>
<p>Stay tuned.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Deploying play-with-docker.com on my machine]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>If you don&apos;t know what <a href="http://play-with-docker.com/?ref=blog.jmkhael.io">play-with-docker</a> is, GO CHECK IT OUT NOW!<br>
It is one of the Moby cool hacks winners! (The other one is <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a> by <a href="https://twitter.com/alexellisuk?ref=blog.jmkhael.io">@alexellisuk</a> - <a href="https://blog.jmkhael.io/serverless-but-on-my-own-servers/">check my post about it here</a>)</p>
<h2 id="playwithdockerpwd">play-with-docker - PWD</h2>
<p>So, what is Play With Docker?</p>
<blockquote>
<p>Hacked by two Docker</p></blockquote>]]></description><link>https://blog.jmkhael.io/deploying-play-with-docker-com-on-my-machine/</link><guid isPermaLink="false">653d5697cf37c50001d2405b</guid><category><![CDATA[deploy-play-with-docker]]></category><category><![CDATA[play-with-docker]]></category><category><![CDATA[on-my-machine]]></category><category><![CDATA[moby-cool-hack]]></category><category><![CDATA[dockercon]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Sat, 22 Apr 2017 19:41:43 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>If you don&apos;t know what <a href="http://play-with-docker.com/?ref=blog.jmkhael.io">play-with-docker</a> is, GO CHECK IT OUT NOW!<br>
It is one of the Moby cool hacks winners! (The other one is <a href="https://github.com/alexellis/faas?ref=blog.jmkhael.io">FaaS</a> by <a href="https://twitter.com/alexellisuk?ref=blog.jmkhael.io">@alexellisuk</a> - <a href="https://blog.jmkhael.io/serverless-but-on-my-own-servers/">check my post about it here</a>)</p>
<h2 id="playwithdockerpwd">play-with-docker - PWD</h2>
<p>So, what is Play With Docker?</p>
<blockquote>
<p>Hacked by two Docker captains, Marcos Nils(<a href="https://twitter.com/marcosnils?ref=blog.jmkhael.io">@marcosnils</a>) and Jonathan Leibiusky(<a href="https://twitter.com/xetorthio?ref=blog.jmkhael.io">@xetorthio</a>), basically, Play with Docker is a Docker playground which you can run directly in your browser. With this, you have no excuse anymore to, well, not play with docker...</p>
</blockquote>
<p>In the below screenshot I&apos;ve deployed a local PWD, and in it you see a swarm of 5, (1 manager, 4 workers) running locally on my machine, with a stack deployed.</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/04/Screenshot-from-2017-04-22-21-20-22.png" alt="pwd-local" loading="lazy"></p>
<h2 id="butiwantedminetoo">But I wanted mine too</h2>
<p>If for whatever reason you want to deploy this on your hardware or VMs, you can (Give access to people via the browser on premises without AWS cost or whatnot), just follow along this quick and dirty post.</p>
<p>What I wanted to do is some Docker-inception. Have a PWD running in my local Swarm and in it a Swarm running LinuxKit :)</p>
<pre><code>git clone https://github.com/franela/play-with-docker
cd play-with-docker/
docker pull franela/dind

sudo apt install golang-go

export GOPATH=$HOME/.go
go get -v -d -t ./...
docker-compose up
</code></pre>
<p>that&apos;s it!</p>
<p>Head over to <a href="http://localhost/?ref=blog.jmkhael.io">http://localhost</a> and you can start clicking &quot;Add New Instance&quot;</p>
<h3 id="letstrytodeployastackontoitnow">Let&apos;s try to deploy a stack onto it now:</h3>
<p>Create an instance, you&apos;ll get a shell, then on it run:</p>
<pre><code>docker swarm init --advertise-addr eth0
</code></pre>
<p>You&apos;ll get something like the below output:</p>
<pre><code>To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-31ovfkdk8wrna2y3igjzdfqhdm0e72ghksb7m441j1hxr1wtwh-81smoz5hu4mrdqzblrydjh86i \
    10.0.0.7:2377
</code></pre>
<p>You can join other workers in if you&apos;d like. To do so, click &quot;Add New Instance&quot; again and paste the command in the shell to join your workers.</p>
<p>Then, let&apos;s deploy our monitoring stack, which basically has portainer.io and manomarks/visualizer:</p>
<pre><code>curl -o docker-compose-stack-monitoring.yml \
https://raw.githubusercontent.com/jmkhael/compose-samples/master/docker-compose-stack-monitoring.yml

docker stack deploy -c docker-compose-stack-monitoring.yml monitoring
docker stack ps monitoring
</code></pre>
<p>and here you&apos;ll see that the services are up and running!</p>
<pre><code>ID            NAME                    IMAGE                        NODE   DESIRED STATE  CURRENT STATE           ERROR  PORTS
qjqciab49qqa  monitoring_viz.1        manomarks/visualizer:latest  node5  Running        Running 30 minutes ago
ske7lcocg8v6  monitoring_portainer.1  portainer/portainer:latest   node5  Running        Running 32 minutes ago
[node5] (local) root@10.0.0.7 ~
</code></pre>
<p>Sweet! It took me much more time to write this blog than to have play-for-docker deployed locally!</p>
<h2 id="bonus">Bonus</h2>
<p>Basically, I want to build the redis os from the keynote in PWD from the Moby cool hack!</p>
<p>Beyond this point, you are left alone in the Docker inception world...</p>
<h3 id="preparelinuxkit">Prepare LinuxKit</h3>
<pre><code>apk update
apk upgrade
apk add --no-cache go
export GOPATH=~/.go
go get -v -d -t ./...  

git clone https://github.com/linuxkit/linuxkit
cd linuxkit
make
</code></pre>
<p>Snipped output below:</p>
<pre><code>mkdir -p bin
tar cf - vendor src/initrd src/pad4 -C src/cmd/moby . | docker run --rm --net=none --log-driver=none -i  linuxkit/go-compile:4513068d9a7e919e4ec42e2d7ee879ff5b95b7f5@sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5 --package github.com/linuxkit/linuxkit --ldflags &quot;-X main.GitCommit=22514db912b9bec73e2a3c3ffd1611633c25b9db -X main.Version=&quot;0.0&quot; &quot; -o bin/moby &gt; tmp_moby_bin.tar
Unable to find image &apos;linuxkit/go-compile:4513068d9a7e919e4ec42e2d7ee879ff5b95b7f5@sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5&apos; locally
sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5: Pulling from linuxkit/go-compile
627beaf3eaaf: Pulling fs layer
...
49418cbb2668: Pull complete
Digest: sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5
Status: Downloaded newer image for linuxkit/go-compile@sha256:bdfadbe3e4ec699ca45b67453662321ec270f2d1a1dbdbf09625776d3ebd68c5
gofmt...
govet...
golint...
ineffassign...
go build...
...
gofmt...
govet...
golint...
ineffassign...
go build...
tar xf tmp_linuxkit_bin.tar &gt; bin/linuxkit
rm tmp_linuxkit_bin.tar
touch bin/linuxkit
</code></pre>
<p>If all goes well, you&apos;ll have two binaries created under bin directory: <strong>moby</strong> and <strong>linuxkit</strong>. As per this <a href="https://github.com/linuxkit/linuxkit/pull/1695?ref=blog.jmkhael.io">pr</a>:</p>
<ul>
<li><strong>moby</strong>: just does the simple build case,</li>
<li><strong>linuxkit</strong>: is useful to push and run the constructed image</li>
</ul>
<pre><code>jmkhael@jmkhael-lx:~/workspace/linuxkit
$ ls bin/
linuxkit  moby
</code></pre>
<blockquote>
<p>I&apos;ve had to patch the Makefile so it works in PWD (It worked without modifications on my local machine directly. <a href="https://blog.jmkhael.io/moby-and-linuxkit-building-a-custom-minimal-immutable-linux-distributions/">as per the previous post</a>)<br>
I&apos;ve cheated a bit. I&apos;ve added <code>-v /root/.go:/go</code> to the Docker run command for GO_COMPILE to have the dependencies.</p>
</blockquote>
<h2 id="buildingtheredisossampleproject">Building the Redis OS sample project</h2>
<p>So, let&apos;s make our OS:</p>
<pre><code>make
./bin/moby build projects/demo/redis-os/redis-os
</code></pre>
<p>output of the command:</p>
<pre><code>Extract kernel image: linuxkit/kernel:4.9.x
Add init containers:
Process init image: linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b
Process init image: linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
Process init image: linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b
Add onboot containers:
Add service containers:
  Create OCI config for linuxkit/dhcpcd:0d4012269cb142972fed8542fbdc3ff5a7b695cd
  Create OCI config for redis:3.0.7-alpine
Add files:
Create outputs:
  redis-os-bzImage redis-os-initrd.img redis-os-cmdline
</code></pre>
<h2 id="testingtheredisos">Testing the Redis OS</h2>
<p>For that, just execute <code>linuxkit run</code> with the image. This will leverage qemu (on Linux) to run your OS in a VM! On Mac, all this given by <a href="https://github.com/moby/hyperkit?ref=blog.jmkhael.io">moby/HyperKit</a>. - note that as of the time of writing, Hyperkit only supports Mac.</p>
<blockquote>
<p>&quot;HyperKit is a toolkit for embedding hypervisor capabilities in your application. Supported backends are:<br>
gcp<br>
hyperkit [macOS]<br>
qemu [linux]<br>
vmware<br>
packet&quot;</p>
</blockquote>
<p>Note that if you want to access the machine from outside, make sure to set the ip for the VM:</p>
<pre><code>bin/linuxkit run redis-os
</code></pre>
<p>After a very short wait, you&apos;ll see a shell!</p>
<p>Let&apos;s abuse netcat to test redis-server from the image itself:</p>
<pre><code>(printf &quot;PING\r\n&quot;; sleep 1) | nc localhost 6379
+PONG
(echo PING; sleep 1) | nc localhost 6379
+PONG
</code></pre>
<p>If you want to connect from the host machine,(where you built the os-redis image), you need to pass additional parameters for linuxkit/qemu runner (introduced by this <a href="https://github.com/linuxkit/linuxkit/pull/1713?ref=blog.jmkhael.io">pull request</a>)</p>
<pre><code>linuxkit run qemu -publish 6379:6379/tcp redis-os
</code></pre>
<p>You can then run on the host:</p>
<pre><code>(printf &quot;PING\r\n&quot;; sleep 1) | nc localhost 6379
+PONG
(echo PING; sleep 1) | nc localhost 6379
+PONG
</code></pre>
<blockquote>
<p>Enjoy your redis-os built by LinuxKit in PWD in Docker!</p>
</blockquote>
<h3 id="diagnostics">Diagnostics</h3>
<p>If you need to diagnose why stuff are not working, <a href="https://github.com/nicolaka/netshoot?ref=blog.jmkhael.io">netshoot</a> docker image can save your day!</p>
<pre><code>docker run -it --net host nicolaka/netshoot
</code></pre>
<p>and in it, run for instance tcpdump:</p>
<pre><code>tcpdump -s 65535 tcp port 6379 -i any
</code></pre>
<p>and see the magic happens:</p>
<pre><code>13:34:20.880434 IP localhost.38050 &gt; localhost.6379: Flags [S], seq 3409053076, win 43690, options [mss 65495,sackOK,TS val 239977870 ecr 0,nop,wscale 7], length 0
13:34:20.880447 IP localhost.6379 &gt; localhost.38050: Flags [S.], seq 195769136, ack 3409053077, win 43690, options [mss 65495,sackOK,TS val 239977870 ecr 239977870,nop,wscale 7], length 0
13:34:20.880458 IP localhost.38050 &gt; localhost.6379: Flags [.], ack 1, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 0
13:34:20.880487 IP localhost.38050 &gt; localhost.6379: Flags [P.], seq 1:6, ack 1, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 5: RESP &quot;PING&quot;
13:34:20.880493 IP localhost.6379 &gt; localhost.38050: Flags [.], ack 6, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 0
13:34:20.881104 IP localhost.6379 &gt; localhost.38050: Flags [P.], seq 1:8, ack 6, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 7: RESP &quot;PONG&quot;
13:34:20.881112 IP localhost.38050 &gt; localhost.6379: Flags [.], ack 8, win 342, options [nop,nop,TS val 239977870 ecr 239977870], length 0
13:34:21.880774 IP localhost.38050 &gt; localhost.6379: Flags [F.], seq 6, ack 8, win 342, options [nop,nop,TS val 239978120 ecr 239977870], length 0
13:34:21.881299 IP localhost.6379 &gt; localhost.38050: Flags [F.], seq 8, ack 7, win 342, options [nop,nop,TS val 239978121 ecr 239978120], length 0
13:34:21.881319 IP localhost.38050 &gt; localhost.6379: Flags [.], ack 9, win 342, options [nop,nop,TS val 239978121 ecr 239978121], length 0

</code></pre>
<h2 id="cleaningup">Cleaning up</h2>
<p>When ready, and you want to stop this Redis OS, type <code>halt</code> in the VM shell. Notice that it takes more time to shutdown than to boot!</p>
<p>You can also kill linuxkit ;)</p>
<p>You should also remove the PWD running containers...</p>
<h2 id="next">Next</h2>
<p>Now, how can I put SwarmKit to handle a hierarchical Swarms built in PWD built on Docker? My head hurt now... and I have a flight to catch!</p>
<blockquote>
<p>Au revoir Austin! Keep Austin weird!</p>
</blockquote>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Moby and LinuxKit: Building a custom minimal, immutable Linux distributions]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>You can also have a go at the interactive tutorial I built here: <a href="http://training.play-with-docker.com/LinuxKit/?ref=blog.jmkhael.io">LinuxKit 101: building the redis-os from DockerCon2017<br>
</a></p>
</blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">You can now build your first <a href="https://twitter.com/hashtag/LinuxKit?src=hash&amp;ref=blog.jmkhael.io">#LinuxKit</a> OS interactively in the web through PWD <a href="https://t.co/T0z3b8MYjU?ref=blog.jmkhael.io">https://t.co/T0z3b8MYjU</a> thx to <a href="https://twitter.com/jmkhael?ref=blog.jmkhael.io">@jmkhael</a>. <a href="https://twitter.com/moby?ref=blog.jmkhael.io">@moby</a> <a href="https://twitter.com/docker?ref=blog.jmkhael.io">@docker</a></p>&#x2014; Marcos Nils (@marcosnils) <a href="https://twitter.com/marcosnils/status/863887434542710784?ref=blog.jmkhael.io">May 14, 2017</a></blockquote>]]></description><link>https://blog.jmkhael.io/moby-and-linuxkit-building-a-custom-minimal-immutable-linux-distributions/</link><guid isPermaLink="false">653d5697cf37c50001d2405a</guid><category><![CDATA[docker]]></category><category><![CDATA[moby]]></category><category><![CDATA[linuxkit]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Thu, 20 Apr 2017 03:02:34 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>You can also have a go at the interactive tutorial I built here: <a href="http://training.play-with-docker.com/LinuxKit/?ref=blog.jmkhael.io">LinuxKit 101: building the redis-os from DockerCon2017<br>
</a></p>
</blockquote>
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">You can now build your first <a href="https://twitter.com/hashtag/LinuxKit?src=hash&amp;ref=blog.jmkhael.io">#LinuxKit</a> OS interactively in the web through PWD <a href="https://t.co/T0z3b8MYjU?ref=blog.jmkhael.io">https://t.co/T0z3b8MYjU</a> thx to <a href="https://twitter.com/jmkhael?ref=blog.jmkhael.io">@jmkhael</a>. <a href="https://twitter.com/moby?ref=blog.jmkhael.io">@moby</a> <a href="https://twitter.com/docker?ref=blog.jmkhael.io">@docker</a></p>&#x2014; Marcos Nils (@marcosnils) <a href="https://twitter.com/marcosnils/status/863887434542710784?ref=blog.jmkhael.io">May 14, 2017</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
<h2 id="mobyandlinuxkit">Moby and LinuxKit?</h2>
<p>So, <a href="http://2017.dockercon.com/?ref=blog.jmkhael.io">DockerCon2017</a> is amazing!</p>
<p>As you should know by now, Docker introduced the Moby project!<br>
If you missed it, go read the announcement here by <a href="https://twitter.com/solomonstre?ref=blog.jmkhael.io">Solomon Hykes</a>. <a href="https://blog.docker.com/2017/04/introducing-the-moby-project/?ref=blog.jmkhael.io">https://blog.docker.com/2017/04/introducing-the-moby-project/</a></p>
<p>At it&apos;s core, <a href="https://github.com/linuxkit/linuxkit?ref=blog.jmkhael.io">LinuxKit</a>.</p>
<blockquote>
<p>LinuxKit, a toolkit for building custom minimal, immutable Linux distributions.</p>
</blockquote>
<h2 id="buildmoby">Build Moby</h2>
<p>I like to get my hands dirty. So let&apos;s build one of the examples supplied to understand more.</p>
<h3 id="prerequisites">Prerequisites</h3>
<p>But first, install qemu if you haven&apos;t done so yet. You&apos;ll probably need build-essentials too.</p>
<pre><code>sudo apt install qemu
</code></pre>
<p>Then just clone and build the <strong>Moby</strong> tools:</p>
<pre><code>git clone https://github.com/linuxkit/linuxkit
cd linuxkit/
make 
sudo make install
</code></pre>
<p>If all goes well, you&apos;ll have two binaries created under bin directory: <strong>moby</strong> and <strong>linuxkit</strong>. As per this <a href="https://github.com/linuxkit/linuxkit/pull/1695?ref=blog.jmkhael.io">pr</a>:</p>
<ul>
<li><strong>moby</strong>: just does the simple build case,</li>
<li><strong>linuxkit</strong>: is useful to push and run the constructed image</li>
</ul>
<p>Let&apos;s make sure it works:</p>
<pre><code>moby
</code></pre>
<p>and see the usage output:</p>
<pre><code>Please specify a command.

USAGE: moby [options] COMMAND

Commands:
  build       Build a Moby image from a YAML file
  version     Print version information
  help        Print this message

Run &apos;moby COMMAND --help&apos; for more information on the command

Options:
  -q	Quiet execution
  -v	Verbose execution

</code></pre>
<h2 id="buildoneoftheexamples">Build one of the examples</h2>
<p>Cool. Let&apos;s build the sshd example, which should produce a kernel:4.9, with some services, among them, linuxkit/sshd</p>
<pre><code>cd examples/
moby build sshd.yml
</code></pre>
<p>After about a minute or so:</p>
<pre><code>linuxkit run sshd
</code></pre>
<p>... after a while...</p>
<pre><code>Starting containerd

Welcome to LinuxKit

                            ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;&quot;\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/


  / # INFO[0000] starting containerd boot...                   module=containerd
  INFO[0000] starting debug API...                         debug=&quot;/run/containerd/debug.sock&quot; module=containerd
  INFO[0000] loading monitor plugin &quot;cgroups&quot;...           module=containerd
  INFO[0000] loading runtime plugin &quot;linux&quot;...             module=containerd
  INFO[0000] loading snapshot plugin &quot;snapshot-overlay&quot;...  module=containerd
  INFO[0000] loading grpc service plugin &quot;content-grpc&quot;...  module=containerd
  INFO[0000] loading grpc service plugin &quot;runtime-grpc&quot;...  module=containerd
  INFO[0000] loading grpc service plugin &quot;images-grpc&quot;...  module=containerd
  INFO[0000] loading grpc service plugin &quot;rootfs-grpc&quot;...  module=containerd
  INFO[0000] loading grpc service plugin &quot;healthcheck-grpc&quot;...  module=containerd
  INFO[0000] loading grpc service plugin &quot;metrics-grpc&quot;...  module=containerd
  INFO[0000] starting GRPC API server...                   module=containerd
  INFO[0000] containerd successfully booted in 0.107088s   module=containerd
   - 000-sysctl
   - dhcpcd
   - rngd
   - sshd
</code></pre>
<p>Once the machine booted up, check it&apos;s kernel is 4.9 built by moby and that sshd is running:</p>
<pre><code>/ # uname -a
Linux moby-525400123456 4.9.22-moby #1 SMP Fri Apr 14 12:32:33 UTC 2017 x86_64 Linux

/ # pgrep -l sshd
404 /usr/sbin/sshd
</code></pre>
<p>Nice! Cannot get easier than that. (Well, with Docker, it will... you just wait)</p>
<h2 id="next">Next</h2>
<p>Where to go next? Maybe we will build something tailored to a particular stack, or tailored for HPC/GPUs maybe?</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Continuously deploying (and backing up) my blog]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>As you should know if you scroll to the bottom of my pages, my blog is</p>
<blockquote>
<p>&quot;Proudly published with Docker, Ghost and ABC Theme on my Raspberry Pi&quot;</p>
</blockquote>
<p>And as you should also know by now, I am pretty much lazy.</p>
<blockquote>
<p>If I won the award for laziness,</p></blockquote>]]></description><link>https://blog.jmkhael.io/continuously-deploying-and-backing-up-my-blog/</link><guid isPermaLink="false">653d5697cf37c50001d24059</guid><category><![CDATA[continuous-deployment]]></category><category><![CDATA[blog]]></category><category><![CDATA[ghost]]></category><category><![CDATA[docker]]></category><category><![CDATA[namecheap]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Fri, 14 Apr 2017 13:13:40 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>As you should know if you scroll to the bottom of my pages, my blog is</p>
<blockquote>
<p>&quot;Proudly published with Docker, Ghost and ABC Theme on my Raspberry Pi&quot;</p>
</blockquote>
<p>And as you should also know by now, I am pretty much lazy.</p>
<blockquote>
<p>If I won the award for laziness, I would send somebody to pick it up for me.</p>
</blockquote>
<p><strong>Problem</strong></p>
<p>My Raspberry Pi is hanging on the floor, the blog being served from an SD card (ouch!) and the whole thing is within reach of my iRobot Roomba Vacuum, which managed to bring down my blog several times already :)</p>
<blockquote>
<p>This seems like a recipe for failure!</p>
</blockquote>
<p>But, instead of mounting an external disk and serving my blog from it, or worse moving my Raspberry Pi away from the Roomba, in this blog post we will setup our Continuous deployment of the blog and favor high availability and resilience use cases (and laziness)!</p>
<p><strong>What we will do</strong></p>
<p>To do that, we will:</p>
<ol>
<li>Build a docker image for the blog without it&apos;s data</li>
<li>Prepare the data and load it as a Docker volume</li>
<li>Push the volume over to an S3 bucket, a Dropbox folder or a google drive one</li>
<li>Setup dyndns client for Namecheap (this is where I bought my domain name)</li>
</ol>
<p>Once we have these three elements, upgrading, deploying, or replicating our blog is a matter of a simple Jenkins job or a shell script.</p>
<p>Ok. Let&apos;s go!</p>
<h2 id="buildadockerimagefortheblogwithoutthedata">Build a Docker image for the blog (without the data)</h2>
<p>Note that for the sake of using my rather old Raspberry Pi to serve my blog, I am basing my Docker image on an already package image done by <a href="https://twitter.com/alexellisuk?ref=blog.jmkhael.io">@alexellisuk</a> for an ARM V6. If you have a different architecture for your Pi, (or x86), you can find other images. Check out his Git repo here: <a href="https://github.com/alexellis/ghost-on-docker?ref=blog.jmkhael.io">https://github.com/alexellis/ghost-on-docker</a></p>
<p>I am customizing a bit to account for my domain name, and replacing bcryptjs by bcrypt, as the later is much more quicker. (Especially on Rpi)</p>
<pre><code>FROM alexellis2/ghost-armv6:0.11.2

RUN sed -i s/my-ghost-blog.com/jmkhael.io/g config.js
RUN npm install bcrypt
RUN sed -i &quot;s/require(&apos;bcryptjs&apos;)/require(&apos;bcrypt&apos;)/&quot; core/server/models/user.js
</code></pre>
<p>You can also just clone and adapt my repo to suit your needs:</p>
<pre><code>git clone https://github.com/jmkhael/blog
pushd blog/jmkhael.io
</code></pre>
<p>Time to build the image:</p>
<pre><code>docker build -t blog-0-11-2 .
</code></pre>
<p>This should have prepared a docker image, which we will be using below.</p>
<h2 id="preparethedataandloaditasadockervolume">Prepare the data and load it as a Docker volume</h2>
<p>Let&apos;s prepare a folder where the data will be stored on disk:</p>
<pre><code>mkdir -p /home/pi/google-drive/ghost-content/
</code></pre>
<p>It is time to run our Ghost blog in a Docker container:</p>
<pre><code>docker run --name blog-0-11-2 \
   -d -p 80:2368 \
   -v /home/pi/google-drive/ghost-content/:/var/www/ghost/content/ \
   blog-0-11-2
</code></pre>
<blockquote>
<p>Of course, you know by now that I prefer to launch everything as a Service in a Docker Swarm ;)</p>
</blockquote>
<p>Wait a (rather big) moment for it to startup, create the schemas and all that.<br>
You can now login to the blog at <a href="http://localhost/?ref=blog.jmkhael.io">http://localhost</a>.</p>
<p>(substitute localhost with the Raspberry Pi or the machine name/or ip where you started the container)</p>
<h2 id="pushthevolumeovertogoogledrive">Push the volume over to google drive</h2>
<p>We will be using <strong>drive</strong> tool from <a href="https://github.com/odeke-em/drive?ref=blog.jmkhael.io">https://github.com/odeke-em/drive</a>.</p>
<h3 id="installationonaraspberrypi">installation on a Raspberry Pi</h3>
<p>Make sure to chose from the releases page <a href="https://github.com/odeke-em/drive/releases?ref=blog.jmkhael.io">https://github.com/odeke-em/drive/releases</a>, the latest version which works for your architecture:</p>
<p>Given that I am running on an ARM v6 (to get yours, execute a <code>uname -a</code>):</p>
<pre><code class="language-bash">cd /tmp
wget wget https://github.com/odeke-em/drive/releases/download/v0.3.8/drive_armv6
chmod +x drive-armv6
sudo cp drive-armv6 /usr/local/bin/gdrive
cd ~
gdrive version
</code></pre>
<h3 id="initgdrive">Init gdrive</h3>
<p>Navigate to the folder in which you want to store google drive root, and call <code>gdrive init</code>:</p>
<pre><code class="language-bash">cd /home/pi/google-drive/ghost-content/
gdrive init
</code></pre>
<p>This will ask you to visit a url to grant the app an OAuth token. Follow that; then paste the token on the command line and press Enter.</p>
<p>Afterwards you can push the folder using:</p>
<pre><code>gdrive push -quiet /home/pi/google-drive/ghost-content/
</code></pre>
<p>You can also pull it when you need to clone it or replicate on another machine:</p>
<pre><code>gdrive pull -quiet /home/pi/google-drive/ghost-content/
</code></pre>
<p>That great. But not enough! We can go further.<br>
Let&apos;s write a small shell script to backup the drive, and put it in a cron:</p>
<p><code>/home/pi/blog/backup.sh</code></p>
<pre><code>#!/bin/bash
echo Starting backup...
/usr/local/bin/gdrive \
    push -no-prompt -exclude-ops \
    delete /home/pi/google-drive/ghost-content
echo Done.
</code></pre>
<p>Now give execution rights and add it to a cron:</p>
<pre><code>chmod a+x /home/pi/blog/backup.sh

crontab -e
</code></pre>
<p>Then add the below line to the end:</p>
<pre><code>30 * * * * bash /home/pi/blog/backup.sh &gt; /tmp/backup.txt
</code></pre>
<p>To do the same into an S3 bucket, or a Dropbox folder you can follow my other guides.</p>
<h2 id="setupdyndnsclientfornamecheap">Setup dyndns client for namecheap</h2>
<p>For the below section, you will need to buy a Namecheap domain (for as little as few dollars). Once done, you need to login and retrieve dyndns password to be used below.</p>
<p>Check the below screenshots to see where to do that:</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/04/nc-manage-domain.png" alt="scr1" loading="lazy"><br>
<img src="https://blog.jmkhael.io/content/images/2017/04/nc-dyndns-obfuscated.png" alt="scr2" loading="lazy"></p>
<p>We will also be using ddclient to update the DNS entry for the domain.</p>
<p><code>sudo nano /etc/ddclient.conf</code></p>
<p>The login is your domain name and the password is retrieved from the second picture from the field <strong>Dynamic DNS Password</strong></p>
<pre><code># Configuration file for ddclient generated by debconf
#
# /etc/ddclient.conf
use=web, web=dynamicdns.park-your-domain.com/getip
daemon=3600
protocol=namecheap
server=dynamicdns.park-your-domain.com
login=jmkhael.io
password=&apos;&lt;my namecheap password goes here&gt;&apos;
@, www, api, blog
</code></pre>
<p>Force a ddclient update then make sure to restart the service:</p>
<pre><code>sudo ddclient --force
sudo service ddclient restart
</code></pre>
<p>Put it in a crontab, so we update namecheap each and every while:</p>
<pre><code>sudo crontab -e
</code></pre>
<p>then add the below line to the end and save:</p>
<pre><code>45 04 * * * /usr/sbin/ddclient --force
</code></pre>
<p>wait a while, and navigate to your domain name and see your blog!</p>
<p><strong>Some useful links for dealing with ddclient and Namecheap</strong></p>
<p><a href="http://workshop.botter.ventures/2014/02/02/how-to-use-ddclient-with-namecheap/?ref=blog.jmkhael.io">http://workshop.botter.ventures/2014/02/02/how-to-use-ddclient-with-namecheap/</a><br>
<a href="https://help.ubuntu.com/community/DynamicDNS?ref=blog.jmkhael.io">https://help.ubuntu.com/community/DynamicDNS</a></p>
<p><strong>Setup reverse proxy and SSL (Optional)</strong></p>
<ul>
<li>Check the following blog posts to setup reverse proxy as <a href="https://blog.jmkhael.io/load-balance-a-swarm-service-behind-ha-proxy-with-automatic-reconfiguration/">HAProxy</a> or <a href="https://blog.jmkhael.io/traefik-as-a-dynamic-reverse-proxy-for-docker-swarm/">Traefik</a> for your Swarm.</li>
</ul>
<h2 id="whatiscomingnext">What is coming next</h2>
<p>In next blog posts, I might document how to:</p>
<ul>
<li>Setup ssl on reverse proxy</li>
<li>Healthcheck/monitor the blog externally (uptime monitoring or something)</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Deploy Swarm Services with the new docker `stack` and a compose file!]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>On of the new additions of <a href="https://blog.docker.com/2017/01/whats-new-in-docker-1-13/?ref=blog.jmkhael.io">Docker 1.13</a> is the ability to use compose files to deploy swarm mode services!</p>
<p>This means that we can use docker-compose files to provision Swarm services.</p>
<p>That also means that we do not need anymore to type all the long <code>docker service create</code></p>]]></description><link>https://blog.jmkhael.io/deploy-swarm-services-with-the-new-docker-stack-and-a-compose-file-2/</link><guid isPermaLink="false">653d5697cf37c50001d24055</guid><category><![CDATA[docker]]></category><category><![CDATA[docker-swarm]]></category><category><![CDATA[docker-stack-deploy]]></category><category><![CDATA[stack-deploy-compose-file]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Thu, 26 Jan 2017 15:08:26 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>On of the new additions of <a href="https://blog.docker.com/2017/01/whats-new-in-docker-1-13/?ref=blog.jmkhael.io">Docker 1.13</a> is the ability to use compose files to deploy swarm mode services!</p>
<p>This means that we can use docker-compose files to provision Swarm services.</p>
<p>That also means that we do not need anymore to type all the long <code>docker service create</code> commands.<br>
A long list of docker service create commands would be simply replaced by a command like the below:</p>
<pre><code>docker stack deploy --compose-file=docker-compose.yml my_stack
</code></pre>
<p>In this blog post, we will see that in action and discuss what is covered and what still lacks.</p>
<h2 id="lifebeforedockerstackdeploy">Life before Docker stack deploy</h2>
<p>Or precisely, before <code>docker stack deploy --compose-file &lt;Path to a Compose file&gt;</code> we had to type a lot and maintain a shell script to start our services accross the Swarm.</p>
<p>What made things worse, is that before the addition of this command, as developers, we loved the docker-compose command to deploy a stack on our machines. But as you know, docker-compose couldn&apos;t benefit from all the nodes of the swarm cluster. It gave us a warning like the below:</p>
<pre><code>docker-compose up -d

WARNING: The Docker Engine you&apos;re using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use the bundle feature of the Docker experimental build.

More info:
https://docs.docker.com/compose/bundles
</code></pre>
<p>So even if you had a compose-file for local testing, you would have to prepare a set of commands to create the service on the Swarm and align those! Talk about technical debt...</p>
<p>Let&apos;s take a simple example where we want to deploy two service to monitor the swarm.</p>
<p>These two service I tend to always create first thing on my Swarms are the <a href="https://github.com/ManoMarks/docker-swarm-visualizer?ref=blog.jmkhael.io">Visualizer</a> and <a href="http://portainer.io/?ref=blog.jmkhael.io">Portainer</a>. Here is how I used to do so:</p>
<pre><code>docker service create \
  --publish 9000:9000 \
  --name portainer \
  --constraint=node.role==manager \
  --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
  portainer/portainer 

docker service create \
  --publish=9090:8080 \
  --limit-cpu 0.5 \
  --name=viz \
  --constraint=node.role==manager \
  --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
  dockersamples/visualizer
</code></pre>
<h2 id="lifeafterdockerstackdeploy">Life after Docker stack deploy</h2>
<p>Let&apos;s now deploy our <code>monitoring</code> stack again, but this time with the new shiny way:</p>
<pre><code>curl -o docker-compose-stack-monitoring.yml \
https://raw.githubusercontent.com/jmkhael/compose-samples/master/docker-compose-stack-monitoring.yml

docker stack deploy -c docker-compose-stack-monitoring.yml monitoring
</code></pre>
<p>The first command downloaded the Compose file docker-compose-stack-monitoring.yml from the <a href="https://github.com/jmkhael/compose-samples?ref=blog.jmkhael.io">jmkhael/compose-samples</a> repository.<br>
The second command creates the services which form what I called the monitoring stack.</p>
<p>Note from the below output that it does incrementally handle new service:</p>
<pre><code>Creating service monitoring_viz
Updating service monitoring_portainer (id: jbt006a7yoi8t0ok941b358k2)
</code></pre>
<p>If you check the created services, you&apos;ll see portainer and visualizer:</p>
<pre><code>docker service ls
ID            NAME                  MODE        REPLICAS  IMAGE
jbt006a7yoi8  monitoring_portainer  replicated  1/1       portainer/portainer:latest
wqfb3odzmnfh  monitoring_viz        replicated  1/1       dockersamples/visualizer:latest
</code></pre>
<p>that&apos;s neat!</p>
<p>The <a href="https://github.com/jmkhael/compose-samples/blob/master/docker-compose-stack-monitoring.yml?ref=blog.jmkhael.io">docker-compose-stack-monitoring.yml</a> file look like this:</p>
<pre><code>version: &apos;3&apos;

services:

  portainer:
    image: portainer/portainer
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - 9000:9000
    deploy:
      placement:
        constraints: [node.role == manager]

  viz:
    image: dockersamples/visualizer
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      placement:
        constraints: [node.role == manager]
    ports:
      - 9090:8080
</code></pre>
<p>Note that the docker-compose file uses the version 3, introduced with Docker 1.13. (Check the schema <a href="https://github.com/aanand/compose-file/blob/master/schema/data/config_schema_v3.0.json?ref=blog.jmkhael.io">here</a>)</p>
<p>You can use some nice configurations under the deploy section such as deployment mode (replicated or global), replicas count (replicas: 3) or labels...</p>
<pre><code>deploy:
  mode: replicated
  replicas: 2
  labels: [APP=CONQUER_UNIVERSE]
</code></pre>
<h2 id="iseverythingcovered">Is everything covered?</h2>
<p>TL;DR:</p>
<p>The short answer is of course, No.</p>
<p>The longer answer is around these lines:</p>
<h3 id="networks">Networks</h3>
<p>No support for attachable networks yet in the docker-compose v3.</p>
<h3 id="extendsnotsupported">Extends not supported</h3>
<p>You cannot use the extends keyword. But there is a quick workaround for that. You&apos;d need to resolve the docker-compose keyword by issuing:</p>
<pre><code>docker-compose config &gt; docker-compose-resolved.yml 
</code></pre>
<h3 id="unsupporteddockercomposev2keywords">Unsupported docker-compose v2 keywords</h3>
<p>The below keywords are still <a href="https://github.com/aanand/compose-file/blob/8b762b24ea40ea5ceda5aac2dd1cd465d0fe6d42/types/types.go?ref=blog.jmkhael.io">not supported</a>.</p>
<ul>
<li>&quot;build&quot;,</li>
<li>&quot;cap_add&quot;,</li>
<li>&quot;cap_drop&quot;,</li>
<li>&quot;cgroup_parent&quot;,</li>
<li>&quot;devices&quot;,</li>
<li>&quot;dns&quot;,</li>
<li>&quot;dns_search&quot;,</li>
<li>&quot;domainname&quot;,</li>
<li>&quot;external_links&quot;,</li>
<li>&quot;ipc&quot;,</li>
<li>&quot;links&quot;,</li>
<li>&quot;mac_address&quot;,</li>
<li>&quot;network_mode&quot;,</li>
<li>&quot;privileged&quot;,</li>
<li>&quot;read_only&quot;,</li>
<li>&quot;restart&quot;,</li>
<li>&quot;security_opt&quot;,</li>
<li>&quot;shm_size&quot;,</li>
<li>&quot;stop_signal&quot;,</li>
<li>&quot;tmpfs&quot;</li>
</ul>
<p>That&apos;s it for this post. Now go deploy some stacks!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Ansible quick guide]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>As you start setting up swarms, you quickly get tired of doing the same commands all over the place, on each node that is.</p>
<p>In this blog post, we are going to document a quick (and dirty) way to start using ansible and that to run some shell commands on</p>]]></description><link>https://blog.jmkhael.io/ansible-3/</link><guid isPermaLink="false">653d5697cf37c50001d24051</guid><category><![CDATA[ansible]]></category><category><![CDATA[raspberry-pi]]></category><category><![CDATA[raspi]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Fri, 20 Jan 2017 16:17:45 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>As you start setting up swarms, you quickly get tired of doing the same commands all over the place, on each node that is.</p>
<p>In this blog post, we are going to document a quick (and dirty) way to start using ansible and that to run some shell commands on the whole swarm, be it to set it up or do some housekeeping.</p>
<blockquote>
<p><a href="https://www.ansible.com/?ref=blog.jmkhael.io">Ansible</a>. Deploy apps. Manage systems. Crush complexity.<br>
Ansible helps you build a strong foundation for DevOps.</p>
</blockquote>
<p>Let&apos;s go.</p>
<h2 id="preparation">Preparation</h2>
<p>first off, let&apos;s install ansible and sshpass:</p>
<p>This is as easy as doing:</p>
<pre><code>apt-get install ansible -y
apt-get install sshpass -y
</code></pre>
<p>Ansible needs to be able to access the machines, and we don&apos;t want to type each time a password. So we basically need to configure ssh password based or passwor-dless based access to the machines.</p>
<p>This post will show both:</p>
<h2 id="configurepasswordbasedlogins">Configure password based logins</h2>
<p>Make sure to backup the ansible configuration before we mess everything:<br>
<code>sudo cp /etc/ansible/hosts /etc/ansible/hosts.orig</code></p>
<p>Let&apos;s edit it, <code>sudo vi /etc/ansible/hosts</code>:</p>
<pre><code>[all:vars]
ansible_port=22
ansible_connection=ssh
ansible_ssh_user=uburoot
ansible_ssh_pass=uburoot

[workers]
mx7264vm
mx7265vm
</code></pre>
<p>Time to run some ansible commands!</p>
<p>Let&apos;s try:</p>
<pre><code>ansible all -m shell -a &quot;docker ps&quot;

mx7264vm | SUCCESS | rc=0 &gt;&gt;
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

mx7265vm | SUCCESS | rc=0 &gt;&gt;
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
</code></pre>
<p>Ok, nothing is running on the cluster.</p>
<p>To see how the Docker daemons are getting started:</p>
<pre><code>ansible all -m shell -a &quot;pgrep -a docker&quot;
</code></pre>
<p>To claim some disk space back:</p>
<pre><code>ansible all -m shell -a &quot;docker system prune --all --force&quot;
</code></pre>
<p>I hope you get the idea :)</p>
<h2 id="configurepasswordlessbasedlogins">Configure password-less based logins</h2>
<p>Let&apos;s first generate an ssh key on the first machine:</p>
<pre><code>ssh-keygen -t rsa
</code></pre>
<p>Always from the first machine, login to the second machine and create the .ssh folder:</p>
<pre><code>ssh uburoot@mx7265vm mkdir -p .ssh
</code></pre>
<p>Now, we should add the public key to the authorized_keys on the target machine:</p>
<pre><code>cat /root/.ssh/id_rsa.pub | ssh uburoot@mx7265vm &apos;cat &gt;&gt; .ssh/authorized_keys&apos;
</code></pre>
<p>If all went according to plan, you should be able to ssh into the second machine without entering a password! Sweet.</p>
<pre><code>ssh uburoot@mx7264vm

Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-53-generic x86_64)
root@mx7264vm:~#
</code></pre>
<p>Do that for all your machines, or use an ansible password based script to set this up and then switch to a password-less login.</p>
<p>In a later post we will write a playbook most probably to configure the Docker daemon flags (connect to an internal registry or to connect to a host socket...)</p>
<p>Stay tuned!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Jhipster my Raspberry Pi!]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>If you don&apos;t know what <a href="https://jhipster.github.io/?ref=blog.jmkhael.io">JHipster</a> is, stop now and go check it out!</p>
<p>Now that you are back, in this blog post, we will build a Netflix Stack using Jhipster on the Raspberry Pi and we will deploy it on a Raspberry Pi Docker Swarm!</p>
<p>But for</p>]]></description><link>https://blog.jmkhael.io/jhipster-my-raspberry-pi/</link><guid isPermaLink="false">653d5697cf37c50001d24053</guid><category><![CDATA[jhipster]]></category><category><![CDATA[raspberry-pi]]></category><category><![CDATA[microservice]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Wed, 11 Jan 2017 14:55:14 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>If you don&apos;t know what <a href="https://jhipster.github.io/?ref=blog.jmkhael.io">JHipster</a> is, stop now and go check it out!</p>
<p>Now that you are back, in this blog post, we will build a Netflix Stack using Jhipster on the Raspberry Pi and we will deploy it on a Raspberry Pi Docker Swarm!</p>
<p>But for that to happen, we need to build a Docker Raspberry Pi image for JHipster (and make it more hip if that is possible)</p>
<p>As a plus, we will do a demo, which would go like that:</p>
<ol>
<li>pull <a href="https://hub.docker.com/r/jmkhael/rpi-jhipster/?ref=blog.jmkhael.io">jmkhael/rpi-jhipster</a> (to be created below)</li>
<li>do some jhipster magic to create a Netflix microservice stack</li>
<li>build and deploy the Docker stack on the Raspberry Pi swarm!</li>
</ol>
<p>Let&apos;s Go.</p>
<h2 id="dockerizetheraspberrypi">Dockerize the Raspberry Pi</h2>
<p>As a pre-requisites, you&apos;d need to have Docker up and running on the Raspberry Pi.</p>
<h6 id="dockerinstallationsonrasperrypi">Docker installations on Rasperry Pi</h6>
<ul>
<li>install docker: <code>curl -sSL https://get.docker.com | sh</code></li>
<li>install <a href="https://github.com/hypriot/arm-compose?ref=blog.jmkhael.io">docker-compose</a> for Arm by following the below commands:</li>
</ul>
<p>bash:</p>
<pre><code>sudo apt-get update
sudo apt-get install -y apt-transport-https
echo &quot;deb https://packagecloud.io/Hypriot/Schatzkiste/debian/ jessie main&quot; | sudo tee /etc/apt/sources.list.d/hypriot.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 37BBEE3F7AD95B3F

sudo apt-get update
sudo apt-get install docker-compose
</code></pre>
<p>Confirm that everything is fine by running:</p>
<pre><code>docker info
docker-compose --version
</code></pre>
<p>Now is the time to build the JHipster Arm image.</p>
<h2 id="jhipsteronraspberrypi">Jhipster on Raspberry Pi</h2>
<p>We need to adapt the project&apos;s Dockerfile so it generates an image which we could run on the  Raspberry Pi.</p>
<p>If you try to run the jhipster/jhipster docker image, it would fail with the dreaded <code>panic exec format.</code> or equivalent, depending on your luck :)</p>
<h3 id="createdockerfilerpi">Create Dockerfile.rpi</h3>
<p>I won&apos;t repeat here the Dockerfile, you can see it on my Github.</p>
<p><a href="https://github.com/jmkhael/generator-jhipster/blob/master/Dockerfile.rpi?ref=blog.jmkhael.io">https://github.com/jmkhael/generator-jhipster/blob/master/Dockerfile.rpi</a></p>
<p>(I still need to do a pull request on the original project to have this natively.)</p>
<h3 id="buildtheimage">Build the image:</h3>
<pre><code>docker build -t jmkhael/rpi-jhipster -f Dockerfile.rpi .
</code></pre>
<h2 id="runjhipsterthedockerway">Run JHipster the Docker way!</h2>
<p>In order to be able to play with (or git commit) the generated files by JHipster, we will create some directories and mount them as volumes in the container.</p>
<p>Create working directory:</p>
<pre><code>mkdir -p jhipster/app
mkdir -p jhipster/app/.m2
mkdir -p jhipster/app/.gradle
</code></pre>
<p>Give ownership of this directory to jhipster user (id 1000)</p>
<pre><code>chown -R 1000 jhipster/app
</code></pre>
<p>In order to be able to execute Docker commands from within the container, we will need to pass the docker group as the group-add flag, so JHipster container can launch docker commands. (discussed <a href="https://github.com/jhipster/generator-jhipster/issues/4804?ref=blog.jmkhael.io#issuecomment-270117037">here</a>)</p>
<p>Now we can run Jhipster&apos;s Docker container on the raspberry Pi and allow it to execute Docker commands on the host!</p>
<pre><code>docker run --name jhipster \
    --group-add $(cat /etc/group | grep docker | awk -F&quot;:&quot; &apos;{print $3}&apos;) \
    -v $(which docker):/usr/bin/docker \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v $(pwd)/jhipster/app/.m2:/home/jhipster/.m2 \
    -v $(pwd)/jhipster/app/.gradle:/home/jhipster/.gradle \
    -v $(pwd)/jhipster/app:/home/jhipster/app \
    -p 8080:8080 -p 9000:9000 -p 3001:3001 -d -t jmkhael/rpi-jhipster
</code></pre>
<p>At this point, Docker should give you the container id in response. If you see anything else, feel free to share in the comments.</p>
<p>Make sure everything works well by executing a shell in the image, and maybe executing a <code>yo jhipster</code> and a <code>docker info</code> commands in there if you feel adventurous:</p>
<pre><code>docker exec -it jhipster bash

jhipster@9df16edc8e52:~/app$ 
</code></pre>
<p>Note that you can stop and start this container if needed using:</p>
<pre><code>docker stop jhipster
docker start jhipster
</code></pre>
<p>Sweet! Time to build our application.</p>
<h2 id="buildourapplicationstack">Build our application stack</h2>
<p>Let&apos;s prepare a directory and call JHipster to generate it:</p>
<pre><code>mkdir blog
cd blog
yo jhipster
yo jhipster:docker-compose
</code></pre>
<p>Answer this in order to have a monolithic application, Angular 1.x, named blog, MySQL, No caching, Gradle build, Social Login, Websockets, English and French support, Gatling and Cucumber!</p>
<pre><code>./gradlew bootRepackage -Pprod buildDocker
</code></pre>
<p>If you need to force the regeneration of the application:</p>
<pre><code>rm -rf src/main
yo jhipster --force --with-entities
</code></pre>
<p>(For fun, try running:</p>
<pre><code>bower install bootstrap-material-design#0.3.0 --save
</code></pre>
<p>then rebuild the application.)</p>
<p>Once ready, go ahead and deploy the application using the generated docker-compose file:</p>
<pre><code>docker-compose up -d

WARNING: The Docker Engine you&apos;re using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All    containers will be scheduled on the current node.

To deploy your application across the swarm, use the bundle feature of the Docker experimental build.

More info:
https://docs.docker.com/compose/bundles

Recreating rpiblog_blog-app_1
blog-mysql is up-to-date
</code></pre>
<p>Navigate to <a href="http://pi1:8080/?ref=blog.jmkhael.io">http://pi1:8080</a> and see your application:</p>
<p><img src="https://blog.jmkhael.io/content/images/2017/01/rpi-jhipster-material-design.png" alt="rpi-jhispter-material-design" loading="lazy"></p>
<p>You can find the resulting application on <a href="https://github.com/jmkhael/rpi-blog?ref=blog.jmkhael.io">https://github.com/jmkhael/rpi-blog</a>.</p>
<h1 id="changestotheoriginaldockerfile">Changes to the (original) Dockerfile</h1>
<p>Below are the changes done on the Dockerfile in order to make it compatible with the Arm processor:</p>
<ol>
<li>Modify the base image to rpi-node</li>
<li>I needed to install oracle jdk8 instead of openjdk, as it suffers from the below stack.</li>
<li>Skip node, npm installation</li>
<li>Skip changing ownership of /usr/lib/node_modules</li>
</ol>
<p>Stack:</p>
<pre><code>Exception in thread &quot;main&quot; javax.net.ssl.SSLHandshakeException: 
   sun.security.validator.ValidatorException: PKIX path validation failed: 
   java.security.cert.CertPathValidatorException: signature check failed
</code></pre>
<p>This is also discussed <a href="https://www.mynethome.de/2016/06/10/openjdk-on-raspberrypi-raspian-fallback-to-oracle-jdk/?ref=blog.jmkhael.io">here</a></p>
<h2 id="todo">TODO</h2>
<p>I still have todo the below when time permits.</p>
<h4 id="rpijhipster">rpi-Jhipster</h4>
<p>[] pull request for rpi image</p>
<p>[] override Docker image names for rpi in <code>./node_modules/generator-jhipster/generators/generator-constants.js:const DOCKER_JAVA_JRE = &apos;openjdk:8-jre-alpine&apos;;</code></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[mongoDB aggregation pipelines]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="whyuseanaggregationpipeline">Why use an aggregation pipeline?</h1>
<p>In this post we will give an example of an aggregation pipeline step by step. It would be as a light tutorial to touch on the subject. We will start with the given context and expose the problem afterwards, then write an aggregation pipeline and</p>]]></description><link>https://blog.jmkhael.io/mongodb-aggregation-pipelines/</link><guid isPermaLink="false">653d5697cf37c50001d24052</guid><category><![CDATA[mongodb]]></category><category><![CDATA[aggregation-pipelines]]></category><category><![CDATA[gamesparks]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Fri, 30 Dec 2016 20:51:27 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="whyuseanaggregationpipeline">Why use an aggregation pipeline?</h1>
<p>In this post we will give an example of an aggregation pipeline step by step. It would be as a light tutorial to touch on the subject. We will start with the given context and expose the problem afterwards, then write an aggregation pipeline and dissect it!</p>
<blockquote>
<p>The aggregate pipeline is a framework for data aggregation modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into aggregated results.<br>
<a href="https://docs.mongodb.com/manual/core/aggregation-pipeline/?ref=blog.jmkhael.io">https://docs.mongodb.com/manual/core/aggregation-pipeline/</a></p>
</blockquote>
<p>READY? Let&apos;s go.</p>
<h2 id="given">Given</h2>
<p>Given a bunch of documents in a mongoDB collection like the below.<br>
Let&apos;s imagine for a moment that those are events generated by a game, concerning win or loss (only, for simplification). Each kind of event has some specific data to it. So we would have a bunch of documents like so:</p>
<pre><code>{
  &quot;playerId&quot;: &quot;c5f348a003840f8&quot;,
  &quot;level&quot;: 0,
  &quot;event&quot;: {
	&quot;score&quot;: 54,
	&quot;damagedBy&quot;: &quot;ASTEROID&quot;,
	&quot;levelKey&quot;: {
	  &quot;id&quot;: 0
	},
	&quot;type&quot;: &quot;lost&quot;
  }
}

{
  &quot;playerId&quot;: &quot;5f348a0038cb8d&quot;,
  &quot;level&quot;: 2,
  &quot;event&quot;: {
	&quot;flawless&quot;: true,
	&quot;collector&quot;: false,
	&quot;levelKey&quot;: {
	  &quot;id&quot;: 2
	},
	&quot;score&quot;: 315,
	&quot;retries&quot;: 3,
	&quot;type&quot;: &quot;won&quot;
  }
}
 ... imagine many events of those, let&apos;s say from a game  ...
</code></pre>
<h2 id="theproblem">The problem</h2>
<p>Lets say we need to construct for a given player (identified by it&apos;s id), an aggregate for each level. This aggregate would tell how many times the level was played, how many times it was won, if it was flawless, if it has the collector property and the score (as coins).</p>
<p>To give you a better idea, the document should look like so:</p>
<pre><code>{
  &quot;played&quot;: 1,
  &quot;won&quot;: 0,
  &quot;flawless&quot;: false,
  &quot;collector&quot;: false,
  &quot;coins&quot;: 38,
  &quot;level&quot;: 5
}
</code></pre>
<ul>
<li><strong>played</strong> = count of events</li>
<li><strong>won</strong> =count of event with type=won</li>
<li><strong>coins</strong> = sum(score),</li>
<li><strong>flawless</strong> and collector are true when at least one event for the level has them true</li>
<li><strong>level</strong> = the level id.</li>
</ul>
<h2 id="solution">Solution</h2>
<p>The below aggregation pipeline does that. Have a look at it and then we will break it down bit by bit.</p>
<pre><code>[{
	&quot;$match&quot;: {
		&quot;playerId&quot;: &quot;c5f348a003840f8&quot;
	}
}, {
	&quot;$group&quot;: {
		&quot;_id&quot;: &quot;$level&quot;,
		&quot;played&quot;: {
			&quot;$sum&quot;: 1
		},
		&quot;won&quot;: {
			&quot;$sum&quot;: {
				&quot;$cond&quot;: [{
					&quot;$eq&quot;: [
						&quot;$event.type&quot;,
						&quot;won&quot;
					]
				},1,0]
			}
		},
		&quot;flawless&quot;: {
			&quot;$sum&quot;: {
				&quot;$cond&quot;: [{
					&quot;$eq&quot;: [
						&quot;$event.flawless&quot;,
						true
					]
				},1,0]
			}
		},
        &quot;collector&quot;: {
			&quot;$sum&quot;: {
				&quot;$cond&quot;: [{
					&quot;$eq&quot;: [
						&quot;$event.collector&quot;,
						true
					]
				},1,0]
			}
		},
		&quot;coins&quot;: {
			&quot;$sum&quot;: &quot;$event.score&quot;
		}
	}
}, {
	&quot;$project&quot;: {
	    &quot;level&quot;: &apos;$_id&apos;,
		&quot;coins&quot;: 1,
		&quot;played&quot;: 1,
		&quot;won&quot;: 1,
		&quot;flawless&quot;:  { $gt: [&apos;$flawless&apos;, 0] } , 
        &quot;collector&quot;: { $gt: [&apos;$collector&apos;, 0] } 
	}
	}]
</code></pre>
<h3 id="letsbreakitdown">Let&apos;s break it down</h3>
<h4 id="abitofdefinitionsfirst">A bit of definitions first</h4>
<p><strong>The aggregate pipeline is</strong></p>
<blockquote>
<p>a framework for data aggregation modeled on the concept of data processing pipelines. Documents enter a multi-stage pipeline that transforms the documents into aggregated results.<br>
<a href="https://docs.mongodb.com/manual/core/aggregation-pipeline/?ref=blog.jmkhael.io">https://docs.mongodb.com/manual/core/aggregation-pipeline/</a></p>
</blockquote>
<p><img src="https://docs.mongodb.com/manual/_images/aggregation-pipeline.png" alt="https://docs.mongodb.com/manual/_images/aggregation-pipeline.png" loading="lazy"></p>
<p>In layman&apos;s terms, a pipeline consists of several stages. Each stage transforms the data as it passes through it, and pass it along the next stage. Easy, right?</p>
<p>Ok, so next logical question you ask is what kind of stages are there?<br>
I am glad you asked! At the time of writing there is around 2Oish operator. (too many to list or explain - check <a href="https://docs.mongodb.com/manual/reference/operator/aggregation/?ref=blog.jmkhael.io#aggregation-pipeline-operator-reference">here</a> if you want to see them all)</p>
<p>For the concern of this blog post, we will use 3 stages to perform our data transformation, namely the match, group and project.</p>
<h4 id="matchstage">$match stage</h4>
<blockquote>
<p>Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match).</p>
</blockquote>
<p>Remember that in the context of our problem we are interested in filtering the events for a given player. We do not want to mix results from different players. That wouldn&apos;t make any sense for the problem we want to solve!</p>
<p>To match the documents for a given player, let&apos;s say id=c5f348a003840f8, our <strong>$match</strong> stage is as easy as this:</p>
<pre><code>{ &quot;$match&quot;: { &quot;playerId&quot;: &quot;c5f348a003840f8&quot; } }
</code></pre>
<p>Great. Now we need to start munching some data, grouping and transforming it. Shall we?</p>
<h4 id="groupstage">$group stage</h4>
<blockquote>
<p>Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.</p>
</blockquote>
<p>If all you&apos;ve understood resembles, blah blah blah blah, don&apos;t be discouraged. Let me try to explain with our example.</p>
<p>Let&apos;s start small. (Most things start like that.)<br>
If we want to see how many times the player played a given level, we would have to group by the level id, and count the number of documents related to that level. (remember we only generate won and lost event in our &quot;complex&quot; game)</p>
<pre><code>{ &quot;$group&quot;: {
      &quot;_id&quot;: &quot;$level&quot;,
      &quot;played&quot;: { &quot;$sum&quot;: 1 }
  }
}
</code></pre>
<ul>
<li><strong>_id</strong>: this is the key you pass to SQL&apos;s GROUP BY, or RxJava groupBy key. Set this to the things you want to group on</li>
<li><strong>played</strong>: here we use an accumulator, the sum. Practically we would add 1 each time we see a document. Thus counting them.</li>
</ul>
<p>Sweet! Let&apos;s make it a bit harder.</p>
<p>In order to see how many time the player won his level, we&apos;d have to count (accumulate the sum) the documents having the <code>event.type == &quot;won&quot;</code></p>
<pre><code>&quot;won&quot;: {
	&quot;$sum&quot;: {
		&quot;$cond&quot;: [{
			&quot;$eq&quot;: [
				&quot;$event.type&quot;,
				&quot;won&quot;
			]
		}, 1, 0]
	}
}
</code></pre>
<p>A bit harder, but not by much! We basically used an equality conditional ($cond and $eq), which operates like a ternary operator, and returns 1 if true or 0 otherwise. and then we sum those. Basically adding 1 each time we see a <strong>won</strong>.</p>
<p>After adding almost the same for the other fields, our documents look like so:</p>
<pre><code>{
   &quot;_id&quot;: 7,
   &quot;played&quot;: 4,
   &quot;won&quot;: 2,
   &quot;flawless&quot;: 2,
   &quot;collector&quot;: 2,
   &quot;coins&quot;: 1044
}
</code></pre>
<p>Pretty close, but not there yet.</p>
<blockquote>
<p>inner voice: I wish there were a way to reshape somehow the document.</p>
</blockquote>
<h4 id="projectstage">$project stage</h4>
<blockquote>
<p>Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document.</p>
</blockquote>
<p>Great! Santa DO EXIST! :&apos;(</p>
<p>Finally, we will use a projection in order to filter out the _id field, and rename or reshape the others:</p>
<pre><code> &quot;$project&quot;: {
       &quot;level&quot;: &apos;$_id&apos;,
       &quot;_id&quot;: 0,
       &quot;coins&quot;: 1,
       &quot;played&quot;: 1,
       &quot;won&quot;: 1,
       &quot;flawless&quot;:  { $gt: [&apos;$flawless&apos;, 0] } ,
       &quot;collector&quot;: { $gt: [&apos;$collector&apos;, 0] }
 }
</code></pre>
<p>Here is what we are saying:</p>
<ul>
<li><strong>level</strong>: we set it to be equal</li>
<li><strong>_id</strong>: we restrict it from showing into the final document by specifying it as <strong>0</strong></li>
<li><strong>coins played and won</strong> are passed as they are - so we set them to <strong>1</strong></li>
<li><strong>collector and flawless</strong>: we convert it to boolean by checking if we had at least 1 as the sum</li>
</ul>
<p>and that&apos;s it! It was easy :)</p>
<p>I&apos;m pretty sure we could have written that in another way. Maybe you want to tell me about it in the comments?</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Traefik as a dynamic reverse proxy for Docker Swarm]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In this post we will setup Traefik as a Dynamic reverse proxy for a Docker Swarm. We will be able to run the same on a Raspberry Pi or on x86.</p>
<p>If you want to see how to do the same with HAProxy, check this <a href="https://blog.jmkhael.io/load-balance-a-swarm-service-behind-ha-proxy-with-automatic-reconfiguration/">post</a>!</p>
<h4 id="whyadynamicreverseproxyandloadbalancer">Why a Dynamic reverse</h4>]]></description><link>https://blog.jmkhael.io/traefik-as-a-dynamic-reverse-proxy-for-docker-swarm/</link><guid isPermaLink="false">653d5697cf37c50001d2404e</guid><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Mon, 12 Dec 2016 11:43:20 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In this post we will setup Traefik as a Dynamic reverse proxy for a Docker Swarm. We will be able to run the same on a Raspberry Pi or on x86.</p>
<p>If you want to see how to do the same with HAProxy, check this <a href="https://blog.jmkhael.io/load-balance-a-swarm-service-behind-ha-proxy-with-automatic-reconfiguration/">post</a>!</p>
<h4 id="whyadynamicreverseproxyandloadbalancer">Why a Dynamic reverse proxy and load balancer?</h4>
<p>Classic loadblancers and proxies (nginx, haproxy, apache) were built with a static backend in mind and are usually enhanced with other projects such as <a href="https://github.com/vfarcic/docker-flow-proxy?ref=blog.jmkhael.io">Victor Farcic&apos; HA docker-flow-proxy</a> or <a href="https://github.com/jwilder/nginx-proxy/?ref=blog.jmkhael.io">jwilder/nginx</a>. Traefik is built for a dynamic world from the start.</p>
<h4 id="whytraefik">Why Traefik?</h4>
<blockquote>
<p>Tr&#xE6;f&#x26A;k is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease. It supports several backends (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Eureka, Rest API, file...) to manage its configuration automatically and dynamically.</p>
</blockquote>
<p>To be honest, I wanted to try it as <strong>I really like the logo :)</strong><br>
(of course in order to learn a new reverse proxy too)</p>
<p><img src="https://github.com/containous/traefik/raw/master/docs/img/traefik.logo.png" alt="traefik" loading="lazy"></p>
<p>Ok. Let&apos;s go now.</p>
<h4 id="deploytraefikontheswarm">Deploy Traefik on the Swarm</h4>
<h5 id="createanoverlaynetwork">Create an overlay network</h5>
<pre><code>docker network create --driver=overlay traefik-net
</code></pre>
<h5 id="deploytraefik">Deploy Traefik</h5>
<pre><code>docker service create \
--name traefik \
--constraint &apos;node.role==manager&apos; \
--publish 80:80 \
--publish 8080:8080 \
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
--network traefik-net \
traefik:camembert \
--docker \
--docker.swarmmode \
--docker.domain=jmkhael.io \
--docker.watch \
--logLevel=DEBUG \
--web
</code></pre>
<p>We will next deploy some services to mimic the below screenshot. We will configure several frontends serving different hosts while themselves are being served by different backends.</p>
<p><img src="https://docs.traefik.io/img/internal.png" alt="diagrams" loading="lazy"></p>
<h6 id="deployapiservice">Deploy api service</h6>
<pre><code>docker service create \
--name api \
--label &apos;traefik.port=5000&apos; \
--network traefik-net \
jmkhael/myservice:0.0.1
</code></pre>
<h6 id="deploybackofficeservice">Deploy backoffice service</h6>
<pre><code>docker service create \
--name backoffice \
--label &apos;traefik.port=5000&apos; \
--network traefik-net \
jmkhael/myservice:0.0.2
</code></pre>
<p>Scale the backoffice service to 3 instances to match the screenshot:</p>
<pre><code>docker service scale backoffice=3
</code></pre>
<h4 id="deploywebservice">Deploy web service</h4>
<pre><code>docker service create \
--name web \
--label &apos;traefik.port=5000&apos; \
--label traefik.frontend.rule=&quot;Host:jmkhael.io; Path: /web/&quot; \
--network traefik-net \
jmkhael/myservice:0.0.2
</code></pre>
<h4 id="testthis">Test this</h4>
<p>Issue the commands:</p>
<pre><code>curl -H Host:api.jmkhael.io http://0.0.0.0
curl -H Host:backoffice.jmkhael.io http://0.0.0.0
curl -H Host:jmkhael.io http://0.0.0.0/web/
</code></pre>
<p>and we should get valid output, like the below:</p>
<pre><code>I&apos;m 24ab5c2a9402
I&apos;m eec66086b687
I&apos;m aaf5402a2387
</code></pre>
<p>Checking the Visualizer we can see all the services running:<br>
<img src="https://blog.jmkhael.io/content/images/2016/12/viz-traefik.png" alt="viz" loading="lazy"></p>
<p>Checking <a href="http://stratus-clay:8080/?ref=blog.jmkhael.io">http://stratus-clay:8080/</a> we can reach the Web dashboard of Traefik and see our frontends and backends well defined:<br>
<img src="https://blog.jmkhael.io/content/images/2016/12/traefik-web-dashboard.png" alt="web-dashboard" loading="lazy"></p>
<p>All this happening like...</p>
<p><img src="http://i.giphy.com/ujUdrdpX7Ok5W.gif" alt="magic" loading="lazy"></p>
<h2 id="runningthesamethingontheraspberrypi">Running the same thing on the Raspberry Pi</h2>
<h3 id="deploytraefikonrpi">Deploy Traefik on Rpi</h3>
<pre><code>docker service create \
--name traefik \
--constraint &apos;node.role==manager&apos; \
--publish 81:80 \
--publish 8081:8080 \
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
--network traefik-net \
hypriot/rpi-traefik \
--docker \
--docker.swarmmode \
--docker.domain=jmkhael.io \
--docker.watch \
--logLevel=DEBUG \
--web
</code></pre>
<h3 id="deploytwoapiendpointsservice">Deploy two API Endpoints Service</h3>
<h4 id="onetorespondonapijmkhaelio">One to respond on api.jmkhael.io</h4>
<pre><code>docker service create \
--name api \
--label &apos;traefik.port=8000&apos; \
--network traefik-net \
hypriot/rpi-whoami
</code></pre>
<h4 id="anothertorespondonapijmkhaelioproducts">Another to respond on api.jmkhael.io/products/</h4>
<pre><code>docker service create \
--name products \
--label &apos;traefik.port=8000&apos; \
--label traefik.frontend.rule=&quot;Host:api.jmkhael.io; Path: /products/&quot; \
--network traefik-net \
hypriot/rpi-whoami
</code></pre>
<h4 id="deployblogserviceonblogjmkhaelio">Deploy Blog service on blog.jmkhael.io</h4>
<p>Constraint it to node blog as it has the data there... until we handle the statefulness better (nfs?)</p>
<pre><code>docker service create \
--name blog \
--label &apos;traefik.port=2368&apos; \
--label traefik.frontend.rule=&quot;Host:api.jmkhael.io, blog.jmkhael.io;&quot; 
--constraint &apos;node.hostname==blog&apos; \
--network traefik-net \
alexellis2/ghost-on-docker:armv6
</code></pre>
<p>Notice that we&apos;ve written frontend rules for api and blog, as Ghost needs both to be redirected to it...<br>
(that means that we cannot host api endpoints, at least not without thinking of a potential clash, as our /products/ above still works)</p>
<p>Test api</p>
<pre><code>curl -H Host:api.jmkhael.io http://0.0.0.0:81
curl -H Host:api.jmkhael.io http://0.0.0.0:81/products/
</code></pre>
<p>If you check <a href="http://blog.jmkhael.io:81/?ref=blog.jmkhael.io">http://blog.jmkhael.io:81</a>, you&apos;ll see the blog running :)<br>
Sweet!</p>
<p><img src="https://blog.jmkhael.io/content/images/2016/12/ghost-traefik-service.png" alt="ghost-traefik-service" loading="lazy"></p>
<p>Let&apos;s also make sure that our products api endpoint is working too:</p>
<pre><code>curl http://api.jmkhael.io:81/products/
I&apos;m eec66086b687
</code></pre>
<p>Scale app</p>
<pre><code>docker service scale api=3

curl -H Host:api.jmkhael.io http://0.0.0.0
curl -H Host:api.jmkhael.io http://0.0.0.0
curl -H Host:api.jmkhael.io http://0.0.0.0
</code></pre>
<p>This might seem to be &quot;not working&quot; (as expected), because the sessions are kept alive for a while - <a href="https://github.com/containous/traefik/issues/727?ref=blog.jmkhael.io">this issue</a> will &quot;correct&quot; it.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Escape proxy hell with Redsocks]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In this post we will install and configure Redsocks to have transparent proxying.<br>
This was executed on a Raspberry Pi running Jessie and on a Redhat 7.</p>
<p>The same applies modulo the yum/apt-get calls.</p>
<p>In the below we will be redirecting all traffic to <code>myproxy.domain.com:3128</code>. Feel</p>]]></description><link>https://blog.jmkhael.io/escape-proxy-hell-with-redsocks/</link><guid isPermaLink="false">653d5697cf37c50001d2404c</guid><category><![CDATA[proxy-hell]]></category><category><![CDATA[escape-from]]></category><category><![CDATA[redsocks]]></category><dc:creator><![CDATA[Johnny Mkhael]]></dc:creator><pubDate>Fri, 09 Dec 2016 13:03:26 GMT</pubDate><media:content url="https://blog.jmkhael.io/content/images/2016/12/escape-from-hell.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.jmkhael.io/content/images/2016/12/escape-from-hell.png" alt="Escape proxy hell with Redsocks"><p>In this post we will install and configure Redsocks to have transparent proxying.<br>
This was executed on a Raspberry Pi running Jessie and on a Redhat 7.</p>
<p>The same applies modulo the yum/apt-get calls.</p>
<p>In the below we will be redirecting all traffic to <code>myproxy.domain.com:3128</code>. Feel free to replace it with your proxy dns name or ip adress and the correct port.</p>
<h4 id="installredsocks">Install redsocks</h4>
<pre><code>apt-get install redsocks
</code></pre>
<h4 id="configureredsocks">Configure redsocks</h4>
<p>Edit <code>/etc/redsocks.conf</code></p>
<pre><code>base {
    log_debug = off;
    log_info = off;
    log = &quot;file:/var/log/redsocks&quot;;
    daemon = on;
    redirector = iptables;
}

redsocks {
    local_ip = 0.0.0.0;
    local_port = 12345;

    ip = myproxy.domain.com;
    port = 3128;

    type = http-relay;
}

redsocks {
        local_ip = 0.0.0.0;
        local_port = 12346;

        ip = myproxy.domain.com;
        port = 3128;
        type = http-connect;
}
</code></pre>
<h4 id="setuptheiptable">Setup the iptable:</h4>
<p>We will do a set of commands which need sudo rights. Start off with a sudo shell:</p>
<pre><code>sudo bash
</code></pre>
<p>then issue the below commands to create a nat rule to forward all non:</p>
<pre><code>iptables -t nat -N REDSOCKS
iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

iptables -t nat -A REDSOCKS -p tcp --dport 80 -j REDIRECT --to-ports 12346
iptables -t nat -A REDSOCKS -p tcp --dport 443 -j REDIRECT --to-ports 12346
iptables -t nat -A REDSOCKS -p tcp --dport 11371 -j REDIRECT --to-ports 12345

iptables -t nat -A OUTPUT -p tcp -j REDSOCKS

iptables -t nat -A PREROUTING -p tcp --dport 11371 -j REDSOCKS
iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDSOCKS
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDSOCKS
</code></pre>
<p>It should be working at this level. Let&apos;s give it a round of tests.</p>
<h5 id="testinternalandexternalaccess">Test internal and external access</h5>
<h6 id="externalaccess">External access</h6>
<pre><code>wget www.google.com
</code></pre>
<h6 id="internalaccess">Internal access</h6>
<p>Try to get an internal page on your network</p>
<pre><code>wget mywebserver
</code></pre>
<h4 id="persisttheiptablerules">Persist the Iptable rules</h4>
<p>If you restart your machine at this level, you&apos;ll notice that the iptable rules we&apos;ve setup aren&apos;t persisted. To persist them on Debian/Ubuntu install iptables-persistent and follow it&apos;s prompt:</p>
<pre><code>apt-get install iptables-persistent
</code></pre>
<p>For Redhat, a simple method to permanently save iptables rules for IPv4 and IPv6. is:</p>
<pre><code>chkconfig iptables on
service iptables save
</code></pre>
<p>You can always save and restore like so (handle ip4 and ip6):</p>
<pre><code>iptables-save &gt; /etc/sysconfig/iptables
ip6tables-save &gt; /etc/sysconfig/ip6tables

iptables-restore &lt; /etc/sysconfig/iptables
ip6tables-restore &lt; /etc/sysconfig/ip6tables
</code></pre>
<h4 id="thatsallforthispost">That&apos;s all for this post!</h4>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>