<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by aelsabbahy on Medium]]></title>
        <description><![CDATA[Stories by aelsabbahy on Medium]]></description>
        <link>https://medium.com/@aelsabbahy?source=rss-40a070c2e82------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*CqLgilGxZwb3gqXn3e6bDQ.jpeg</url>
            <title>Stories by aelsabbahy on Medium</title>
            <link>https://medium.com/@aelsabbahy?source=rss-40a070c2e82------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 07 May 2026 14:05:52 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@aelsabbahy/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Tutorial: How to test your docker image in half a second]]></title>
            <link>https://medium.com/@aelsabbahy/tutorial-how-to-test-your-docker-image-in-half-a-second-bbd13e06a4a9?source=rss-40a070c2e82------2</link>
            <guid isPermaLink="false">https://medium.com/p/bbd13e06a4a9</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[containers]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[aelsabbahy]]></dc:creator>
            <pubDate>Wed, 15 Mar 2017 11:16:48 GMT</pubDate>
            <atom:updated>2017-03-27T22:54:59.550Z</atom:updated>
            <content:encoded><![CDATA[<p>In this tutorial we’ll walk through a really simple way to write and test docker images. The tests we’ll write will validate the official <a href="https://hub.docker.com/_/nginx/">Nginx</a> docker image using <a href="https://github.com/aelsabbahy/goss">Goss</a> in <strong>~0.5s</strong>.</p><p>When you’re done with this tutorial you’ll have a small YAML file that describes your docker image’s desired state. This will allow you to test this:</p><pre>docker run -p 8080:80 nginx</pre><p>With this:</p><pre>dgoss run -p 8080:80 nginx</pre><p>The tests will run in about a half second, and output the following:</p><pre>INFO: Starting docker container<br>INFO: Container ID: 25d23a24<br>INFO: Running Tests<br>File: /var/log/nginx/error.log: exists: matches expectation: [true]<br>File: /var/log/nginx/error.log: linkedto: matches expectation: [&quot;/dev/stderr&quot;]<br>File: /var/log/nginx/error.log: filetype: matches expectation: [&quot;symlink&quot;]<br>File: /var/log/nginx/access.log: exists: matches expectation: [true]<br>File: /var/log/nginx/access.log: linkedto: matches expectation: [&quot;/dev/stdout&quot;]<br>File: /var/log/nginx/access.log: filetype: matches expectation: [&quot;symlink&quot;]<br>Process: nginx: running: matches expectation: [true]<br>Port: tcp:80: listening: matches expectation: [true]<br>Port: tcp:80: ip: matches expectation: [[&quot;0.0.0.0&quot;]]<br>HTTP: <a href="http://localhost">http://localhost</a>: status: matches expectation: [200]<br>HTTP: <a href="http://localhost">http://localhost</a>: Body: matches expectation: [Welcome to nginx!]<br>Package: nginx: installed: matches expectation: [true]<br>Package: nginx: version: matches expectation: [[&quot;1.11.10-1~jessie&quot;]]</pre><pre>Total Duration: 0.012s<br>Count: 13, Failed: 0, Skipped: 0<br>INFO: Deleting container</pre><p><strong><em>Note:</em></strong><em> If you’re more of a visual person, there’s a video version of this tutorial at the bottom of this blog post.</em></p><h3>Prerequisites</h3><p>In order to follow along this tutorial, you need to have <a href="https://www.docker.com/">Docker</a> installed.</p><h3>Installing our test tool</h3><p>We’ll be using <a href="https://github.com/aelsabbahy/goss">Goss</a> as the testing tool of choice. The installation is simple and only takes a few seconds.</p><pre>curl -fsSL https://goss.rocks/install | sh</pre><p><strong>NOTE:</strong> If you are weary of curl | sh , you can install it manually by following the instructions <a href="https://github.com/aelsabbahy/goss#manual-installation">here</a>.</p><h4>So.. What is <a href="https://github.com/aelsabbahy/goss">Goss</a>?</h4><blockquote>Goss is a YAML based <a href="http://serverspec.org/">serverspec</a> alternative tool for validating a server’s configuration. It eases the process of writing tests by allowing the user to generate tests from the current system state. Once the test suite is written they can be executed, waited-on, or served as a health endpoint.</blockquote><p>More info can be found on the <a href="https://github.com/aelsabbahy/goss">Goss webpage</a>.</p><h3>Writing our test</h3><p>dgoss is a helper tool that comes with Goss to make it extremely easy to write docker tests. Let’s say we run our docker image in the following way:</p><pre>docker run -p 8080:80 nginx:1.11.10</pre><p>To start writing our tests we substitute docker run with dgoss edit:</p><pre>dgoss edit -p 8080:80 nginx:1.11.10</pre><p>This will run the docker image, and drop us into an interactive shell with Goss installed in the container, you will see an output similar to this:</p><pre>INFO: Starting docker container<br>INFO: Container ID: 9468c0c3<br>INFO: Run goss add/autoadd to add resources</pre><p>Once in the interactive shell we can start writing our test suite. Paste in the following commands and they will derive tests from the running container’s state:</p><pre>goss a file /var/log/nginx/access.log /var/log/nginx/error.log<br>goss a process nginx<br>goss a port 80<br>goss a package nginx<br>goss a http <a href="http://localhost">http://localhost</a><br>exit</pre><p><strong>Note:</strong> “a” is short for “add” in Goss.</p><p>After we exit the container will be deleted, and you will now see a goss.yaml in your current directory that contains the following:</p><pre>file:<br>  /var/log/nginx/access.log:<br>    exists: true<br>    mode: &quot;0777&quot;<br>    size: 11<br>    owner: root<br>    group: root<br>    linked-to: /dev/stdout<br>    filetype: symlink<br>    contains: []<br>  /var/log/nginx/error.log:<br>    exists: true<br>    mode: &quot;0777&quot;<br>    size: 11<br>    owner: root<br>    group: root<br>    linked-to: /dev/stderr<br>    filetype: symlink<br>    contains: []<br>package:<br>  nginx:<br>    installed: true<br>    versions:<br>    - 1.11.10-1~jessie<br>port:<br>  tcp:80:<br>    listening: true<br>    ip:<br>    - 0.0.0.0<br>process:<br>  nginx:<br>    running: true<br>http:<br>  <a href="http://localhost">http://localhost</a>:<br>    status: 200<br>    allow-insecure: false<br>    no-follow-redirects: false<br>    timeout: 5000<br>    body: []</pre><p>This can be executed by running:</p><pre>dgoss run nginx</pre><h3>Modifying our tests by hand</h3><p>The YAML file we generated in the last section can be written by hand. The dgoss edit command is intended as a helper to ease the process of writing tests. However, in most cases the generated YAML will need to be modified. Let&#39;s go ahead and do that..</p><p>For the files section, we only care that the log files are symlinked to stdout/stderr, so let’s remove the mode, size, owner, group, and contains checks. Our files section should look as follows:</p><pre>file:<br>  /var/log/nginx/access.log:<br>    exists: true<br>    linked-to: /dev/stdout<br>    filetype: symlink<br>  /var/log/nginx/error.log:<br>    exists: true           <br>    linked-to: /dev/stderr<br>    filetype: symlink</pre><p>For the http check, let’s remove the https related flags and validate that the “Welcome to nginx!” message appears in the response body:</p><pre>http:<br>  <a href="http://localhost">http://localhost</a>:<br>    status: 200<br>    timeout: 5000<br>    body:<br>    - Welcome to nginx!</pre><p>Our YAML file should now be 28 lines:</p><pre>file:<br>  /var/log/nginx/access.log:<br>    exists: true<br>    linked-to: /dev/stdout<br>    filetype: symlink<br>  /var/log/nginx/error.log:<br>    exists: true<br>    linked-to: /dev/stderr<br>    filetype: symlink<br>package:<br>  nginx:<br>    installed: true<br>    versions:<br>    - 1.11.10-1~jessie<br>port:<br>  tcp:80:<br>    listening: true<br>    ip:<br>    - 0.0.0.0<br>process:<br>  nginx:<br>    running: true<br>http:<br>  <a href="http://localhost">http://localhost</a>:<br>    status: 200<br>    timeout: 5000<br>    body:<br>    - Welcome to nginx!</pre><p>Same as before, executing this is simply:</p><pre>dgoss run nginx</pre><h3>What’s next?</h3><p>This tutorial is meant as a quick start showcasing a simple test scenario. For more advanced use cases take see the following resources:</p><ul><li><a href="https://github.com/aelsabbahy/goss">Goss</a> — The tool used in this tutorial</li><li><a href="https://github.com/aelsabbahy/goss/tree/master/extras/dgoss">dgoss</a> — Helper tool packaged with goss, also used in this tutorial</li><li><a href="https://github.com/aelsabbahy/dgoss-examples">dgoss-examples</a> — Repo containing more complex examples of using dgoss to validate docker images</li><li><a href="https://github.com/aelsabbahy/goss/blob/master/docs/manual.md">Goss manual </a>— Goss documentation</li></ul><h3>Video version of this tutorial</h3><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FPEHz5EnZ-FM%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DPEHz5EnZ-FM&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FPEHz5EnZ-FM%2Fhqdefault.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/6641540036737f30df287590a5156f4e/href">https://medium.com/media/6641540036737f30df287590a5156f4e/href</a></iframe><p><strong>If you found this article beneficial, please recommend it to others by clicking the heart.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bbd13e06a4a9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Docker 1.12/Kubernetes simplified health checks and container ordering with Goss]]></title>
            <link>https://medium.com/@aelsabbahy/docker-1-12-kubernetes-simplified-health-checks-and-container-ordering-with-goss-fa8debbe676c?source=rss-40a070c2e82------2</link>
            <guid isPermaLink="false">https://medium.com/p/fa8debbe676c</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[containers]]></category>
            <dc:creator><![CDATA[aelsabbahy]]></dc:creator>
            <pubDate>Tue, 02 Aug 2016 13:42:19 GMT</pubDate>
            <atom:updated>2017-03-27T15:42:17.177Z</atom:updated>
            <content:encoded><![CDATA[<p>In this article we’ll go over some common health check and dependency challenges when using docker standalone or with Kubernetes and how they can easily be remedied with <a href="https://github.com/aelsabbahy/goss">Goss</a> and <a href="https://hub.docker.com/r/aelsabbahy/goss/">Goss docker-images</a>.</p><p><strong>Edit:</strong> I recently released a new tool <a href="https://github.com/aelsabbahy/miniswarm">Miniswarm</a>, in this section of the <a href="https://youtu.be/in1ItGKDr98?t=2m59s">tutorial video</a> I show Goss health checks being used with Docker Swarm.</p><p><strong>So.. What is </strong><a href="https://github.com/aelsabbahy/goss"><strong>Goss</strong></a><strong>?</strong></p><p><em>Note: Unless you’re familiar with Goss v0.2.0, I recommend you read this section.</em></p><blockquote>Goss is a YAML based <a href="http://serverspec.org/">serverspec</a> alternative tool for validating a server’s configuration. It eases the process of writing tests by allowing the user to generate tests from the current system state. Once the test suite is written they can be executed, waited-on, or served as a health endpoint.</blockquote><p>More info can be found on the <a href="https://github.com/aelsabbahy/goss">Goss webpage</a>.</p><p>Example goss.yaml test file:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2620500421228ecd68c52bf61f54e039/href">https://medium.com/media/2620500421228ecd68c52bf61f54e039/href</a></iframe><p>The above goss.yaml file can also be generated by using the following commands on a configured system:</p><pre>goss add dns mysql</pre><pre># &quot;a&quot; is short for &quot;add&quot;<br>goss a addr mysql:3306<br>goss a command &#39;/goss/checks/db_login.sh&#39;</pre><p>Once we have a test suite, we can:</p><ul><li>run it once</li></ul><pre>goss validate</pre><ul><li>keep running it until the system enters a valid state or we timeout</li></ul><pre>goss validate --retry-timeout 30s --sleep 1s</pre><ul><li>serve the tests as a health endpoint</li></ul><pre>goss serve &amp;<br>curl localhost:8080/healthz</pre><pre># JSON endpoint<br>goss serve --format json &amp;<br>curl localhost:8080/healthz</pre><p><strong>Docker Challenge: Running more than one HEALTHCHECK command</strong></p><p>Docker 1.12 introduced the concept of HEALTHCECK, but only allows you to run one command. By letting <a href="https://github.com/aelsabbahy/goss">Goss</a> manage your checks. The goss.yaml file can define as many checks or reference as many scripts/commands as you like.</p><pre>FROM alpine:3.4</pre><pre># Install Goss<br>RUN apk add --no-cache --virtual=goss-dependencies curl ca-certificates &amp;&amp; \<br>    curl -fsSL https://goss.rocks/install | sh &amp;&amp; \<br>    apk del goss-dependencies</pre><pre># Add our checks<br>ADD db_login.sh /goss/checks/db_login.sh<br>ADD goss.yaml /goss/goss.yaml</pre><pre># Use goss to run all our other checkes<br>HEALTHCHECK --interval=1s --timeout=6s CMD goss -g /goss/goss.yaml validate</pre><p>You can view the container health using the following commands:</p><pre># View health check status<br>docker ps container_name</pre><pre># Print out the text of the last 5 checks<br>docker inspect -f &#39;{{ range .State.Health.Log }}{{ println &quot;======\nStart:&quot; .Start }}{{ .Output }}{{end}}&#39; container_name</pre><p><strong>Docker Challenge: Delaying container startup until dependent services are up and running</strong></p><p>If your application can’t gracefully handle missing dependent services, wrap the CMD in a script that calls <a href="https://github.com/aelsabbahy/goss">Goss</a> validate with a retry.</p><pre># Alternatively, the -r option can be set<br># using the GOSS_RETRY_TIMEOUT env variable<br>CMD goss -g /goss/goss.yaml validate -r 5m &amp;&amp; exec my_command..</pre><p><strong>Kubernetes Challenge: Monitoring 3rdParty applications that do not provide a /healthz endpoint</strong></p><p>Create a <a href="http://kubernetes.io/docs/user-guide/pods/multi-container/">multi-container pod</a> and use <a href="https://github.com/aelsabbahy/goss">Goss</a> as a /healthz endpoint. Set the /healthz endpoint as a <a href="http://kubernetes.io/docs/user-guide/pod-states/#container-probes">readiness and/or liveliness probe</a> to control traffic and/or container status.</p><p>To create a healthz container:</p><ul><li>Create goss.yaml and optionally a checks folder in the following structure:</li></ul><pre>.<br>|-- Dockerfile<br>`-- goss/<br>    |-- checks/<br>    |   `-- db_login.sh<br>    `-- goss.yaml</pre><ul><li>Use the goss:onbuild image to build our healtz image:</li></ul><pre>FROM goss:onbuild<br>CMD [&quot;serve&quot;]</pre><p>Example of a mysql deployment with /healthz endpoint:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0400d1324778cdaf57c882b572a83684/href">https://medium.com/media/0400d1324778cdaf57c882b572a83684/href</a></iframe><p><strong>Kubernetes Challenge: Ensure container waits for dependencies to before starting up</strong></p><p>Use the goss:onbuild image to create an image that waits for certain conditions to be met (perhaps another service’s /heathz endpoint). Set it as an init-container. For more information on init-containers, see the Kubernets docs <a href="http://kubernetes.io/docs/user-guide/production-pods/#handling-initialization">here</a> and <a href="https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/container-init.md">here</a>.</p><p>Example Dockerfile:</p><pre>FROM goss:onbuild<br>CMD [&quot;validate&quot;, &quot;--retry-timeout&quot;, &quot;5m&quot;]</pre><p><strong>Parting thoughts</strong></p><p>Check out <a href="https://medium.com/u/9e783a6f12f6">Kelsey Hightower</a>’s great <a href="https://vimeo.com/173610242">talk at Monitorama</a> to see some of the above patterns in action.</p><p><strong>If you found this article informative, please recommend it to others by clicking the heart.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/725/1*prif7-04oPf8Dqo1gvSDsQ.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fa8debbe676c" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>