<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Buildx on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/buildx/</link><description>Recent content in Buildx on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 20 Nov 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/buildx/index.xml" rel="self" type="application/rss+xml"/><item><title>Building Docker images for multiple architectures</title><link>https://blog.iankulin.com/building-docker-images-for-multiple-architectures/</link><pubDate>Mon, 20 Nov 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/building-docker-images-for-multiple-architectures/</guid><description>&lt;p&gt;My little mdserver app has been a good way for me to start experimenting with the the devops side of things, especially building for Docker. Since I wanted to make the Docker image available for ARM Linux &amp;amp; x86 Linux I had a janky shell script that looked like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#5e81ac;font-style:italic"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# Extract the version number from package.json using jq&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;VERSION&lt;span style="color:#81a1c1"&gt;=&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;$(&lt;/span&gt;jq -r .version package.json&lt;span style="color:#81a1c1;font-weight:bold"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker build --platform linux/amd64 -t iankulin/mdserver:$VERSION -t iankulin/mdserver:latest .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker build --platform linux/arm64 -t iankulin/mdserver:arm64-$VERSION -t iankulin/mdserver:arm64-latest .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker push iankulin/mdserver:arm64-$VERSION 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker push iankulin/mdserver:arm64-latest 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker push iankulin/mdserver:$VERSION
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker push iankulin/mdserver:latest 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So I&amp;rsquo;d build two different versions, and use the tags to separate them. In the registry it&amp;rsquo;d look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-10-29-at-3.36.45-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-10-29-at-3.36.45-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But the big official images, for instance Node, have a long list of architectures associated with each tag - these are &lt;a href="https://docs.docker.com/build/building/multi-platform/"&gt;multi-platform images&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To create these, we need to use the &lt;code&gt;docker buildx&lt;/code&gt; feature. If you google how to do this, there&amp;rsquo;s a few mentions of how to &amp;rsquo;turn on&amp;rsquo; this &amp;rsquo;experimental&amp;rsquo; feature. I didn&amp;rsquo;t do that, so perhaps it&amp;rsquo;s been mainstreamed now. What I did to enable it was to enter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker buildx create --use
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then to create my dual architecture image:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker buildx build --push \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--platform linux/arm64,linux/amd64 \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-t iankulin/mdserver:latest .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then 113 seconds later (thank you Apple silicon), this showed up in my Docker Hub:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-10-29-at-3.47.50-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-10-29-at-3.47.50-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lovely!&lt;/p&gt;
&lt;p&gt;Buoyed by success, I decided I should also be shipping a Raspberry Pi version, which I guess is 32 bit ARM? So I dropped this into the CLI:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;docker buildx build --push \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;--platform linux/arm64,linux/amd64,linux/arm/v7 \
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-t iankulin/mdserver:latest .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This was somewhat less successful. I think the story of the building for other architectures with &lt;code&gt;buildx&lt;/code&gt; is that the container has QEMU binaries for them - ie like it&amp;rsquo;s running a little VM to do the build inside of. That&amp;rsquo;s three inception layers in, so I guess that&amp;rsquo;s why it&amp;rsquo;s slow for an alien architecture.&lt;/p&gt;
&lt;p&gt;In any case, this may still work, but at the time of writing, the &lt;code&gt;NPM install&lt;/code&gt; had been running overnight . If this speed turns out to be typical, it&amp;rsquo;s a good reason to look at outsourcing your Docker builds to GitHub actions.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-10-30-at-7.03.18-am.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;With all eight cores pegged at 100% on an M1 MacBook:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-10-30-at-7.05.19-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-10-30-at-7.05.19-am.png" width="1000" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>