<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>devops &amp;mdash; Arturo Linares</title>
    <link>https://arturo.linar.es/tag:devops</link>
    <description></description>
    <pubDate>Sat, 02 May 2026 15:27:54 +0000</pubDate>
    <item>
      <title>Dokku: A Heroku alternative</title>
      <link>https://arturo.linar.es/dokku-a-heroku-alternative?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[&#xA;&#xA;TL;DR: Needed a way to easily deploy and manage legacy and new sites without spending a lot of money. Dokku gives me the awesome Heroku developer experience on a cheap VPS box.&#xA;!--more--&#xA;Since I started working on the web, I&#39;ve been publishing small sites. Usually I use these pet projects to try out new technologies, so most of them don&#39;t share the same technology. Some are almost 10 years old. Of course, I don&#39;t have the time to maintain them and their owners are not interested in spend more resources to bring them up-to-date. So I&#39;m stuck maintaining the hosting for very different projects.&#xA;&#xA;To save on expenses and time I used to host them all in one cheap VPS, but things were becoming complicated as language versions become deprecated. Keeping them in a shared environment is a challenge because different applications use different versions of PHP, databases (some use mysql, others Postgres). I even have .NET core sites running.&#xA;&#xA;This year I decided to find a better solution, where I can keep all together and still make it easy to deploy or create resources on the server. So I tried Azure, AWS, Heroku and several others.&#xA;&#xA;The best ones, of course, were not cheap. I think Heroku is still one of the best one in terms of developer experience. So looking around I came to know Dokku, which is an open source platform similar to Heroku (and it even uses their Buildpacks).&#xA;&#xA;What&#39;s in a Buildpack&#xA;&#xA;Heroku works using Buildpacks. You can picture them as the instructions on how to build and deploy an application. Dokku use these Buildpacks too to create container images and run them.&#xA;&#xA;But, what about the ones with specific requirements? I have some sites that require wkhtmltopdf. Well, it turns out that it is possible to customize the image that Dokku builds by using deploy scripts that run at different stages in the deployment process.&#xA;&#xA;OK, How does it look like?&#xA;&#xA;To deploy a new PHP application that uses a MySQL database, this would be enough (assuming you installed and configured the Dokku bash client):&#xA;&#xA;Create a database&#xA;dokku mysql:create myphpdb&#xA;Create a new application&#xA;dokku apps:create myphpapp&#xA;Allow the application access the database&#xA;dokku mysql:link myphpdb myphpapp&#xA;Deply the application&#xA;git push dokku master&#xA;&#xA;Dokku identifies it is a PHP application if it finds a composer.json file. In it, you can specify the PHP version to use and if you need special extensions, like bcmath. &#xA;&#xA;For example:&#xA;&#xA;&#34;require&#34;: {&#xA;  &#34;php&#34;: &#34;  =7.1&#34;,&#xA;  &#34;ext-bcmath&#34;: &#34;&#34;&#xA;}&#xA;&#xA;You can then configure your PHP application to read the database connection details using environment variables. Once a database is linked to your application you will have in the DATABASEURL environment variable a full DSN to connect to it. If you need to, you can declare more environment variables like this, not necessarily related to the database:&#xA;&#xA;dokku config:set MYSQLDBNAME=myphpapp MYSQL_USERNAME=mysql ...&#xA;&#xA;Advantages&#xA;&#xA;The developer experience. It allows me to manage sites and its resources without leaving the terminal. The experience is very similar to Heroku.&#xA;&#xA;It can be fully automated. For example, pulling database dumps to a development environment, schedule nightly backups and SSL certificate renewals. &#xA;&#xA;Zero downtime deployments.&#xA;&#xA;Kubernetes&#xA;&#xA;But... Dokku works using docker... that&#39;s so 2014. Dokku is already working on Kubernetes support (and should be functional at this point), although I don&#39;t mind to use and old* technology if it works. However, I wish it could use podman to avoid the security risk of having a docker daemon running. &#xA;&#xA;devops&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://i.snap.as/WCQT4If.png" alt=""/></p>

<p><em><strong>TL;DR</strong>: Needed a way to easily deploy and manage legacy and new sites without spending a lot of money. Dokku gives me the awesome Heroku developer experience on a cheap VPS box.</em>

Since I started working on the web, I&#39;ve been publishing small sites. Usually I use these pet projects to try out new technologies, so most of them don&#39;t share the same technology. Some are almost 10 years old. Of course, I don&#39;t have the time to maintain them and their owners are not interested in spend more resources to bring them up-to-date. <strong>So I&#39;m stuck maintaining the hosting for very different projects</strong>.</p>

<p>To save on expenses and time I used to host them all in one cheap VPS, but things were becoming complicated as language versions become deprecated. Keeping them in a shared environment is a challenge because different applications use different versions of PHP, databases (some use mysql, others Postgres). I even have .NET core sites running.</p>

<p>This year I decided to find a better solution, where I can keep all together and still make it easy to deploy or create resources on the server. So I tried Azure, AWS, Heroku and several others.</p>

<p>The best ones, of course, were not cheap. <strong>I think Heroku is still one of the best one in terms of developer experience. So looking around I came to know <a href="http://dokku.viewdocs.io/dokku/" rel="nofollow">Dokku</a></strong>, which is an open source platform similar to Heroku (and it even uses their Buildpacks).</p>

<h2 id="what-s-in-a-buildpack" id="what-s-in-a-buildpack">What&#39;s in a Buildpack</h2>

<p>Heroku works using Buildpacks. You can picture them as the instructions on how to build and deploy an application. Dokku use these Buildpacks too to create container images and run them.</p>

<p>But, what about the ones with specific requirements? I have some sites that require <code>wkhtmltopdf</code>. Well, <strong>it turns out that it is possible to customize the image that Dokku builds by using deploy scripts that run at different stages in the deployment process</strong>.</p>

<h2 id="ok-how-does-it-look-like" id="ok-how-does-it-look-like">OK, How does it look like?</h2>

<p>To deploy a new PHP application that uses a MySQL database, this would be enough (assuming you installed and configured the Dokku <a href="http://dokku.viewdocs.io/dokku/community/clients/" rel="nofollow">bash client</a>):</p>

<pre><code class="language-bash"># Create a database
dokku mysql:create myphp_db
# Create a new application
dokku apps:create myphp_app
# Allow the application access the database
dokku mysql:link myphp_db myphp_app
# Deply the application
git push dokku master
</code></pre>

<p>Dokku identifies it is a PHP application if it finds a <code>composer.json</code> file. In it, you can specify the PHP version to use and if you need special extensions, like <code>bcmath</code>.</p>

<p>For example:</p>

<pre><code class="language-json">&#34;require&#34;: {
  &#34;php&#34;: &#34;&gt;=7.1&#34;,
  &#34;ext-bcmath&#34;: &#34;*&#34;
}
</code></pre>

<p>You can then configure your PHP application to read the database connection details using environment variables. Once a database is linked to your application you will have in the <code>DATABASE_URL</code> environment variable a full DSN to connect to it. If you need to, you can declare more environment variables like this, not necessarily related to the database:</p>

<pre><code class="language-bash">dokku config:set MYSQL_DBNAME=myphpapp MYSQL_USERNAME=mysql ...
</code></pre>

<h2 id="advantages" id="advantages">Advantages</h2>
<ol><li><p><strong>The developer experience</strong>. It allows me to manage sites and its resources without leaving the terminal. The experience is very similar to Heroku.</p></li>

<li><p><strong>It can be fully automated</strong>. For example, pulling database dumps to a development environment, schedule nightly backups and SSL certificate renewals.</p></li>

<li><p><strong>Zero downtime deployments</strong>.</p></li></ol>

<h2 id="kubernetes" id="kubernetes">Kubernetes</h2>

<p>But... Dokku works using docker... that&#39;s so 2014. Dokku is already working on Kubernetes support (and should be functional at this point), although I don&#39;t mind to use and <em>old</em> technology if it works. However, I wish it could use <code>podman</code> to avoid the security risk of having a docker daemon running.</p>

<p><a href="https://arturo.linar.es/tag:devops" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">devops</span></a></p>
]]></content:encoded>
      <guid>https://arturo.linar.es/dokku-a-heroku-alternative</guid>
      <pubDate>Thu, 16 Jul 2020 02:21:04 +0000</pubDate>
    </item>
    <item>
      <title>Easy VRT testing</title>
      <link>https://arturo.linar.es/easy-vrt-testing?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[&#xA;&#xA;I normally work on different and very active projects in several testing environments. I needed a simple and fast way to generate visual regression tests between them, or even to just to compare my local environment to an integration server. However, it was cumbersome to edit backstop configuration files frequently just to change servers, thus I created a tool that simplifies the task a lot:&#xA;&#xA;https://github.com/arturolinares/easy-vrt&#xA;&#xA;!--more--&#xA;&#xA;  It is a Symfony console application that wraps Docker backstop containers to run the tests. The application reads a list of URLs from a CSV file to generate the JSON configuration files for BackstopJS.&#xA;&#xA;Usage&#xA;&#xA;Once the project is installed you will want to compare two sites. Follow these steps:&#xA;&#xA;Generate the backstop scenarios using a CSV file containing the routes to visit.&#xA;Run the tests.&#xA;Browse the results to visualize the differences.&#xA;&#xA;To generate the scenarios use the command vrt:gen. It will use a CSV file with the routes to generate them:&#xA;&#xA;bin/console vrt:gen path/to/routes.csv --ref-domain=http://prod.com --url=http://my-qa.com&#xA;&#xA;You can find a sample of the CSV file in the sample directory. The file has two fields: the route and an optional label. For example:&#xA;&#xA;/,&#34;The Homepage&#34;&#xA;/category/tag,&#xA;&#34;/about-us&#34;, &#34;About US&#34;&#xA;&#xA;You can set the reference domain using the flag --ref-domain. This is normally production. Use the flag --url to specify the domain you want to compare.&#xA;&#xA;Sometimes you need to create several scenarios for the same route but different prefix. For example, when using multilingual sites. To specify the prefixes you can use the --prefix (-p) option:&#xA;&#xA;bin/console vrt:gen path/to/routes.csv -u http://my-qa.com -r prod.com -p es -p en -p fr&#xA;&#xA;The above will generate scenarios for these urls:&#xA;&#xA;/es/&#xA;/en/&#xA;/fr/&#xA;/es/category/tag&#xA;/en/category/tag&#xA;/fr/category/tag&#xA;/es/about-us&#xA;/en/about-us&#xA;/fr/about-us&#xA;&#xA;Until now, you only have configured backstop. To actually run the tests use vrt:run. This command will run backstop using a Docker container. Also, if you want to see what the script is doing, you can change the verbosity with -v, -vv and -vvv.&#xA;&#xA;Finally, to see the report, use vrt:server to browse the diffs.&#xA;&#xA;#devops #testing]]&gt;</description>
      <content:encoded><![CDATA[<p><img src="https://i.snap.as/bCR0UZe.png" alt=""/></p>

<p>I normally work on different and very active projects in several testing environments. I needed a simple and fast way to generate visual regression tests between them, or even to just to compare my local environment to an integration server. However, it was cumbersome to edit backstop configuration files frequently just to change servers, thus I created a tool that simplifies the task a lot:</p>

<p><a href="https://github.com/arturolinares/easy-vrt" rel="nofollow">https://github.com/arturolinares/easy-vrt</a></p>



<blockquote><p>It is a Symfony console application that wraps Docker backstop containers to run the tests. The application reads a list of URLs from a CSV file to generate the JSON configuration files for BackstopJS.</p></blockquote>

<h2 id="usage" id="usage">Usage</h2>

<p>Once the project is installed you will want to compare two sites. Follow these steps:</p>
<ol><li>Generate the backstop scenarios using a CSV file containing the routes to visit.</li>
<li>Run the tests.</li>
<li>Browse the results to visualize the differences.</li></ol>

<p>To <strong>generate the scenarios</strong> use the command <code>vrt:gen</code>. It will use a CSV file with the routes to generate them:</p>

<pre><code>bin/console vrt:gen path/to/routes.csv --ref-domain=http://prod.com --url=http://my-qa.com

</code></pre>

<p>You can find a sample of the CSV file in the <code>sample</code> directory. The file has two fields: the route and an optional label. For example:</p>

<pre><code>/,&#34;The Homepage&#34;
/category/tag,
&#34;/about-us&#34;, &#34;About US&#34;

</code></pre>

<p>You can set the reference domain using the flag <code>--ref-domain</code>. This is normally production. Use the flag <code>--url</code> to specify the domain you want to compare.</p>

<p><strong>Sometimes you need to create several scenarios for the same route but different prefix</strong>. For example, when using multilingual sites. To specify the prefixes you can use the <code>--prefix</code> (<code>-p</code>) option:</p>

<pre><code>bin/console vrt:gen path/to/routes.csv -u [http://my-qa.com](http://my-qa.com) -r prod.com -p es -p en -p fr

</code></pre>

<p>The above will generate scenarios for these urls:</p>

<pre><code>/es/
/en/
/fr/
/es/category/tag
/en/category/tag
/fr/category/tag
/es/about-us
/en/about-us
/fr/about-us

</code></pre>

<p>Until now, you only have configured backstop. <strong>To actually run the tests use</strong> <code>vrt:run</code>. This command will run backstop using a Docker container. Also, if you want to see what the script is doing, you can change the verbosity with <code>-v</code>, <code>-vv</code> and <code>-vvv</code>.</p>

<p>Finally, <strong>to see the report</strong>, use <code>vrt:server</code> to browse the diffs.</p>

<p><a href="https://arturo.linar.es/tag:devops" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">devops</span></a> <a href="https://arturo.linar.es/tag:testing" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">testing</span></a></p>
]]></content:encoded>
      <guid>https://arturo.linar.es/easy-vrt-testing</guid>
      <pubDate>Sun, 12 Apr 2020 05:09:21 +0000</pubDate>
    </item>
  </channel>
</rss>