<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Francesco Tonini</title>
    <description>The latest articles on DEV Community by Francesco Tonini (@francescotonini).</description>
    <link>https://dev.to/francescotonini</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F30039%2F9612ef44-819d-42f9-b994-be4b36b48b83.png</url>
      <title>DEV Community: Francesco Tonini</title>
      <link>https://dev.to/francescotonini</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/francescotonini"/>
    <language>en</language>
    <item>
      <title>5 most common Dockerfile mistakes</title>
      <dc:creator>Francesco Tonini</dc:creator>
      <pubDate>Thu, 25 Feb 2021 08:41:44 +0000</pubDate>
      <link>https://dev.to/francescotonini/5-most-common-dockerfile-mistakes-1ja8</link>
      <guid>https://dev.to/francescotonini/5-most-common-dockerfile-mistakes-1ja8</guid>
      <description>&lt;p&gt;Docker is great. You cannot deny it. Popularity is still growing and the internet is full of examples for every possible programming language, framework, and environment. When it is time to deploy something the first thing I do is search on Google for an example of Dockerfile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwou4yhoas2r7yta58gzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwou4yhoas2r7yta58gzz.png" alt="That's about it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is fine, right? Unfortunately, most of the examples available online are insecure by design. In my first post here on HashNode I am going to explore some common pitfalls and possible solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running as root
&lt;/h2&gt;

&lt;p&gt;This is probably the most underrated issue. By default, containers run as root. Ipotethically, if one gains control of the container, it can cause harm to the host.&lt;/p&gt;

&lt;p&gt;One easy and reliable fix is to create a user inside the container and set it as both the working directory and the running user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:latest&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;useradd &lt;span class="nt"&gt;--create-home&lt;/span&gt; dockeruser
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /home/dockeruser&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; dockeruser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;em&gt;latest&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Many examples' base image use the &lt;em&gt;latest&lt;/em&gt; tag. While it is fine for tutorials, Dockerfiles in production must always pin an image tag that is supposed to not change and break your build.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;latest&lt;/em&gt; tag is updated every time a new version of the container is pushed. Your build can suddenly break.&lt;/p&gt;

&lt;p&gt;Suppose you are deploying a container with &lt;em&gt;python:latest&lt;/em&gt; as a base image. At that time &lt;em&gt;latest&lt;/em&gt; refers to Python 3.6. Weeks later you have to rebuild the image but it fails, dependencies are not fulfilled. Why? I haven't touched them! By now &lt;em&gt;python:latest&lt;/em&gt; refers to Python 3.9 which, incidentally, does not support some of your dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimize the number of layers
&lt;/h2&gt;

&lt;p&gt;Docker creates a layer for each  &lt;code&gt;RUN&lt;/code&gt;, &lt;code&gt;COPY&lt;/code&gt;, and &lt;code&gt;ADD&lt;/code&gt; instruction. The more layers, the slower the container.&lt;br&gt;
Whenever possible, wrap multiple commands into a single layer. Remember that you can use &lt;code&gt;\&lt;/code&gt; to trigger multi-line arguments&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:latest&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    git &lt;span class="se"&gt;\
&lt;/span&gt;    rsync &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Do not create &lt;strong&gt;huge&lt;/strong&gt; containers
&lt;/h2&gt;

&lt;p&gt;One container, one service. Docker containers are not virtual machines. If you have many services to deploy, just create many containers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use layer caching
&lt;/h2&gt;

&lt;p&gt;When building images, Docker looks for images in the cache that can reuse. This way, no duplicate images are created and consecutive builds are faster.&lt;/p&gt;

&lt;p&gt;But there is a catch. If you copy the source code before installing the dependencies, every time you update the code Docker will invalidate every successive instruction. In other words, you are going to install dependencies every time even though they are identical.&lt;br&gt;
Fortunately, there is a quick fix. Simply make sure that layers that do not change frequently are before layers that do.&lt;br&gt;
For instance, instead of copying the whole source code and then run &lt;code&gt;npm install&lt;/code&gt;, just copy &lt;code&gt;package.json&lt;/code&gt;, run &lt;code&gt;npm install&lt;/code&gt; and then copy the rest of the code. This way every change to the source will not trigger &lt;code&gt;npm install&lt;/code&gt; but rather the cache.&lt;/p&gt;

&lt;p&gt;That's about it! There are many more tips and tricks to make Dockerfiles faster, maintainable, and secure. These are the 5 most common that everyone should fix ASAP.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you like it, share and follow me for more! 😀&lt;/em&gt; &lt;/p&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>My solution to the Google HashCode 2020 online round</title>
      <dc:creator>Francesco Tonini</dc:creator>
      <pubDate>Fri, 21 Feb 2020 21:59:14 +0000</pubDate>
      <link>https://dev.to/francescotonini/my-solution-to-the-google-hashcode-2020-online-round-14md</link>
      <guid>https://dev.to/francescotonini/my-solution-to-the-google-hashcode-2020-online-round-14md</guid>
      <description>&lt;p&gt;Hi everyone! This post goes through the story behind the development of my solution for the Google HashCode 2020 online round. If you have never heard of Google HashCode, it is a team coding competition made by Google to solve engineering problems. There is no programming language constraints, just a problem to solve in a fixed amount of time. After the online round, the best teams will be invited by Google for the final round.&lt;/p&gt;

&lt;p&gt;Yesterday's problem was to plan which books to scan from a set of libraries. Each book has its own score and the goal was to maximize the total score of scanned books. The full problem statement will be available on the Google HashCode website shortly.&lt;/p&gt;

&lt;p&gt;Enough of that, let's make our hands dirty. This solution is available on &lt;a href="https://github.com/francescotonini/hashcode-books"&gt;GitHub&lt;/a&gt; and it is written in C# (don't be scared by that, if you known a bit of Java and lambda you'll be fine).&lt;/p&gt;

&lt;h2&gt;
  
  
  A naive approach
&lt;/h2&gt;

&lt;p&gt;First of all, I had to find a metric to sort each library and pick the best ones. I decided to calculate the score of each library, then sort them in descending order, and output it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IOh9Eis6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/plaeo5lm7rjkrljsv1kx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IOh9Eis6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/plaeo5lm7rjkrljsv1kx.png" alt="Oh boy, that's bad"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unsurprisingly, the total score was terrible. What I didn't take into consideration were two main facts: first, two or more libraries may have the same book, but I only need to scan it once; second, what should I do when two libraries have the same score? How should I prioritize one over the other?&lt;/p&gt;

&lt;h2&gt;
  
  
  Less duplicates, more score?
&lt;/h2&gt;

&lt;p&gt;So I was back to the drawing board. This time, when I am facing two or more libraries with the same score, I pick the one with the least signup time, so that to allow more books to be scanned in parallel. Also, the score of a library takes into account only books that haven't been scanned before. That should fix it!&lt;/p&gt;

&lt;h2&gt;
  
  
  So, job done?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5VzO5_FO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5ou6vmoc7z6u7rvmht6u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5VzO5_FO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5ou6vmoc7z6u7rvmht6u.jpg" alt="Well yes, but actually no"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I did improve the score on one dataset, the others were just like the first attempt. Also, the dataset "D" was really slow, but we'll get back to it later on.&lt;/p&gt;

&lt;p&gt;So, as you may expect, I was back to the drawing board again; yet, something wasn't adding up. What if instead to sorting by score, then signup time, I do signup time first, then score?&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Oh well, that was the kind of improvement I was looking for.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AvHVSAPR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3vafiffhkjq8hh35qv4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AvHVSAPR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3vafiffhkjq8hh35qv4f.png" alt="That's better"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About dataset "D - tough choices"
&lt;/h2&gt;

&lt;p&gt;While I was happy with the overall result, I had to find a solution for dataset "D", which on the above implementation was painfully slow. While looking at the data I realized that all books have a score of 65, meaning that I didn't need to calculate the score, I just had to multiply the number of books that can be scanned every day by the number of days and 65. This was fundamental to keep the execution time at a reasonable level (remember that we have a limited amount of time).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This has been a hell of a ride, but it was worth it. It's not the perfect score, but I am more than happy about the result.&lt;/p&gt;

&lt;p&gt;If you would like to see my implementation, head over to &lt;a href="https://github.com/francescotonini/hashcode-books"&gt;GitHub&lt;/a&gt;. If you like this article, please consider sharing it with friends and colleagues. Also, if you have any suggestion, don't be shy. Ciao!&lt;/p&gt;

</description>
      <category>google</category>
      <category>hashcode</category>
      <category>csharp</category>
    </item>
  </channel>
</rss>
