<?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: Pablo Chico de Guzman</title>
    <description>The latest articles on DEV Community by Pablo Chico de Guzman (@pchico83).</description>
    <link>https://dev.to/pchico83</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%2F206381%2F16292217-38be-4da6-ba1a-133e78ab058b.png</url>
      <title>DEV Community: Pablo Chico de Guzman</title>
      <link>https://dev.to/pchico83</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pchico83"/>
    <language>en</language>
    <item>
      <title>Building Docker Images Faster for Webpack</title>
      <dc:creator>Pablo Chico de Guzman</dc:creator>
      <pubDate>Fri, 17 Dec 2021 07:58:33 +0000</pubDate>
      <link>https://dev.to/okteto/building-docker-images-faster-for-webpack-44jc</link>
      <guid>https://dev.to/okteto/building-docker-images-faster-for-webpack-44jc</guid>
      <description>&lt;p&gt;At Okteto we are very passionate about increasing developer productivity. We were looking for ways to improve our container build times when we came across an amazing project, &lt;a href="https://github.com/moby/buildkit" rel="noopener noreferrer"&gt;BuildKit&lt;/a&gt;. BuildKit helps us build Docker images faster than ever. &lt;/p&gt;

&lt;p&gt;But when getting started we found that there were very few practical examples on how one could optimize their Dockerfiles with Buildkit - so we thought why not change that? This article is going to be about how you too can optimize your Docker builds using &lt;a href="https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/syntax.md#run---mounttypecache" rel="noopener noreferrer"&gt;Buildkit caches&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Why
&lt;/h2&gt;

&lt;p&gt;The first question which arises is, why even bother with optimizing your Dockerfiles? Well, the thing is that containers have revolutionized how we build, ship, and run our applications these days. So much so that containers are now heavily integrated into the development cycle and are built over and over - manually or in CI pipelines for testing and live previews.&lt;/p&gt;

&lt;p&gt;The biggest quality of life improvement that comes with better image build times is faster testing and review cycles. The quicker everyone can see and test the changes they make, the more the productivity of the team would increase! We have first-hand witnessed this for our website, but more on that later. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Standard Dockerfile for Webpack
&lt;/h2&gt;

&lt;p&gt;Before we look at how we can speed up build times using BuildKit, let's first see how a standard Dockerfile for Webpack should look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dockerfile&lt;/span&gt;

&lt;span class="s"&gt;FROM node:16 as build&lt;/span&gt;

&lt;span class="s"&gt;WORKDIR /usr/src/app&lt;/span&gt;

&lt;span class="s"&gt;COPY package.json yarn.lock ./&lt;/span&gt;
&lt;span class="s"&gt;RUN yarn install&lt;/span&gt;

&lt;span class="s"&gt;COPY . .&lt;/span&gt;
&lt;span class="s"&gt;RUN yarn build&lt;/span&gt;

&lt;span class="s"&gt;FROM nginx:alpine&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=build /usr/src/app/dist /usr/share/nginx/html&lt;/span&gt;
&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Dockerfile uses a &lt;code&gt;build&lt;/code&gt; step to build the final artifacts, and then, it copies the artifacts to an &lt;code&gt;nginx&lt;/code&gt; image.&lt;/p&gt;

&lt;p&gt;In order to optimize the Dockerfile instructions cache, we are purposefully &lt;strong&gt;first&lt;/strong&gt; copying &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;yarn.lock&lt;/code&gt; to install the runtime dependencies. We don't copy over everything else in this same step since most of the commits don't change the yarn dependencies, allowing this step to be cached in those cases leading to better build times! But this is already a commonly known best practice and BuildKit would help us optimize the process even more.&lt;/p&gt;

&lt;p&gt;The next thing we do is to &lt;code&gt;COPY&lt;/code&gt; all our remaining files from our local folder to our &lt;code&gt;WORKDIR&lt;/code&gt;. Our changes would be made to one of these files so this means that &lt;code&gt;yarn build&lt;/code&gt; is always executed unlike the &lt;code&gt;yarn install&lt;/code&gt; instruction above.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember to configure your &lt;code&gt;.dockerignore&lt;/code&gt; file. In this case, adding &lt;code&gt;.git&lt;/code&gt; or &lt;code&gt;node_modules&lt;/code&gt; to your &lt;code&gt;.dockerignore&lt;/code&gt; file will dramatically reduce the time to send your build context to the docker daemon. This is even more relevant if your build is running on a remote server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Optimizing the Standard Dockerfile
&lt;/h2&gt;

&lt;p&gt;Now that we've looked at how a standard Dockerfile for Webpack looks like, let's see how we can leverage BuildKit caches to further reduce our build times. BuildKit enables us to configure cache folders for the &lt;code&gt;RUN&lt;/code&gt; instructions in our Dockerfile.&lt;/p&gt;

&lt;p&gt;Contents of the BuildKit cache directories persist between builder invocations without invalidating the instruction cache. BuildKit also takes care of compatibility - our builds would work with any contents of the cache directory. This is necessary since another build may overwrite the cache files or GC may clean it if more storage space is needed.&lt;/p&gt;

&lt;p&gt;In our case, we will use BuildKit caches to persist the &lt;a href="https://classic.yarnpkg.com/en/docs/cli/cache" rel="noopener noreferrer"&gt;yarn cache&lt;/a&gt; and the &lt;a href="https://webpack.js.org/configuration/cache/#cachecachedirectory" rel="noopener noreferrer"&gt;webpack cache&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dockerfile.buildkit&lt;/span&gt;

&lt;span class="s"&gt;FROM node:16 as build&lt;/span&gt;

&lt;span class="s"&gt;WORKDIR /usr/src/app&lt;/span&gt;

&lt;span class="s"&gt;COPY package.json yarn.lock ./&lt;/span&gt;
&lt;span class="s"&gt;RUN --mount=type=cache,target=/root/.yarn YARN_CACHE_FOLDER=/root/.yarn yarn install&lt;/span&gt;

&lt;span class="s"&gt;COPY . .&lt;/span&gt;
&lt;span class="s"&gt;RUN --mount=type=cache,target=./node_modules/.cache/webpack yarn build&lt;/span&gt;

&lt;span class="s"&gt;FROM nginx:alpine&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=build /usr/src/app/dist /usr/share/nginx/html&lt;/span&gt;
&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this means is that &lt;code&gt;yarn install&lt;/code&gt; and &lt;code&gt;yarn build&lt;/code&gt; will be much faster. This is because their contents will be cached now onwards instead of them being run from scratch every time like earlier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that we've not covered the installation process for BuildKit in this article since it's fairly simple and is documented well &lt;a href="https://github.com/moby/buildkit#quick-start" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Performance Evaluation
&lt;/h2&gt;

&lt;p&gt;The improvement in build times we saw for our website after using BuildKit was phenomenal! Have a look yourself.&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%2Fpem7j1ujloqqxpc9dfbq.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%2Fpem7j1ujloqqxpc9dfbq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first graph shows the performance improvement we saw whenever we changed a dependency of our website and the second one shows the boost we got from using BuildKit when making code changes.&lt;/p&gt;

&lt;p&gt;This means if you're building your images 100 times a day, you save more than 1 hr 23 mins of build time every day!&lt;/p&gt;

&lt;p&gt;We hope you too can now appreciate how powerful BuildKit is. A change of only two lines of code in your Dockerfile can dramatically decrease your image build times! We hope this article was useful and you too are now able to optimize your Docker builds. &lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webpack</category>
      <category>buildkit</category>
      <category>dockerfile</category>
    </item>
  </channel>
</rss>
