<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>iAmBenzo</title>
      <link>https://iambenzo.com</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://iambenzo.com/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Fri, 11 Jul 2025 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Container Registry SSL and K8s Kind</title>
          <pubDate>Fri, 11 Jul 2025 00:00:00 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/k8s-kind-cr-ssl/</link>
          <guid>https://iambenzo.com/posts/k8s-kind-cr-ssl/</guid>
          <description xml:base="https://iambenzo.com/posts/k8s-kind-cr-ssl/">&lt;h1 id=&quot;context&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#context&quot; aria-label=&quot;Anchor link for: context&quot;&gt;Context&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Often, I want to play with a Kubernetes cluster without having to pay a cloud provider for compute, or by setting up a home lab cluster with &lt;code&gt;kubeadm&lt;&#x2F;code&gt;. In these times, I reach for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kind.sigs.k8s.io&#x2F;&quot;&gt;K8s Kind&lt;&#x2F;a&gt; (although I&#x27;d love to have a home lab cluster).&lt;&#x2F;p&gt;
&lt;p&gt;Simply put, Kind allows me to run a small Kubernetes cluster within Docker&#x2F;Podman&#x2F;You Choose. Whilst the number of pods I can run is limited to the power of my machine, it&#x27;s great for running small proof-of-concepts (PoCs) and exploring the configuration of a product before deploying it to a &lt;em&gt;real&lt;&#x2F;em&gt; cluster.&lt;&#x2F;p&gt;
&lt;p&gt;I do have a small tip that I can share with you now to increase that pod limit if you&#x27;re on a Debian-based machine:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; sysctl fs.inotify.max_user_watches=524288&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; sysctl fs.inotify.max_user_instances=512&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These commands boost the number of file watchers available for the duration of your session, returning those values to their defaults once you reboot. More file watches = more pods.&lt;&#x2F;p&gt;
&lt;p&gt;If Docker&#x2F;Others were already running before you ran these commands, you might want to restart those services.&lt;&#x2F;p&gt;
&lt;p&gt;But that&#x27;s not what I really want to share...&lt;&#x2F;p&gt;
&lt;h1 id=&quot;problem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#problem&quot; aria-label=&quot;Anchor link for: problem&quot;&gt;Problem&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Recently, I decided to spend too much time writing YAML files, in playing with the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;argoproj.github.io&#x2F;&quot;&gt;Argo Project&lt;&#x2F;a&gt;. Mostly to explore some features and generally play with GitOps type processes. As part of my test-bed setup, I deployed &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt; to replicate a scenario where there&#x27;s a Git server and container registry hosted alongside the GitOps tooling.&lt;&#x2F;p&gt;
&lt;p&gt;My goals and reasons aren&#x27;t really important here. The problem I came up against was &lt;em&gt;after&lt;&#x2F;em&gt; I had code repos set up, events firing off workflows to build and push container images, and finally automatic deployment to a target Kubernetes namespace.&lt;&#x2F;p&gt;
&lt;p&gt;All of that worked, as defined in the glorious YAML files I had painstakingly created. The problem was at deployment time: &lt;code&gt;ImagePullBackOff&lt;&#x2F;code&gt; - Kubernetes couldn&#x27;t pull my container images because it couldn&#x27;t verify the self-signed SSL certificate I&#x27;d used for the Forgejo Ingress rule.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;How did I get around that problem?&lt;&#x2F;em&gt; Well, first, I destroyed my Kind cluster.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Was I having a tantrum?&lt;&#x2F;em&gt; Maybe. &lt;em&gt;Would I have needed to nuke everything I created anyway?&lt;&#x2F;em&gt; Unfortunately so.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;resolution&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#resolution&quot; aria-label=&quot;Anchor link for: resolution&quot;&gt;Resolution&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The reason I had to destroy my Kind cluster is that the container image used by Kind as a virtual Kubernetes node doesn&#x27;t seem to contain a text editor. No Vim, no Vi, not even Nano. So I couldn&#x27;t simply shell into the node, make a few edits and &lt;code&gt;service containerd restart&lt;&#x2F;code&gt; my way to happiness.&lt;&#x2F;p&gt;
&lt;p&gt;The first modification I needed to make is in the ContainerD config file. This is typically located at &lt;code&gt;&#x2F;etc&#x2F;containerd&#x2F;config.toml&lt;&#x2F;code&gt; on a Kubernetes node.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kind.sigs.k8s.io&#x2F;docs&#x2F;user&#x2F;private-registries&#x2F;#use-a-certificate&quot;&gt;A bit of reading&lt;&#x2F;a&gt; pointed me to a way to modify this file upon cluster creation. Cool. I modified my Kind cluster definition (another YAML file) to look a little like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;kind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Cluster&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;kind.x-k8s.io&#x2F;v1alpha4&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;plaything&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerdConfigPatches&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-chomping-indicator z-yaml&quot;&gt;-&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    [plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;.registry]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;      config_path = &amp;quot;&#x2F;etc&#x2F;containerd&#x2F;certs.d&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;nodes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;role&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;control-plane&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;extraPortMappings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;80&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hostPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;80&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;TCP&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;443&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hostPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;443&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;TCP&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The magic is under the &lt;code&gt;containerdConfigPatches&lt;&#x2F;code&gt; key. It&#x27;s basically telling ContainerD that some configuration exists under the defined directory.&lt;&#x2F;p&gt;
&lt;p&gt;The next thing I needed to do was to create some config under that &lt;code&gt;config_path&lt;&#x2F;code&gt; for my self-hosted container registry. I had my Forgejo instance running under the &lt;code&gt;git.benzo.test&lt;&#x2F;code&gt; hostname, thanks to some &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dnsmasq.org&#x2F;doc.html&quot;&gt;Dnsmasq&lt;&#x2F;a&gt; magic that could have also been achieved with an extra entry in my machine&#x27;s &lt;code&gt;hosts&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: &lt;code&gt;git.benzo.test&lt;&#x2F;code&gt; is a local-only hostname, which isn&#x27;t internet facing - it won&#x27;t work for you.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;m telling you the hostname because it defines the location and the contents of the next file we need to create: &lt;code&gt;&#x2F;etc&#x2F;containerd&#x2F;certs.d&#x2F;&amp;lt;hostname&amp;gt;&#x2F;hosts.toml&lt;&#x2F;code&gt;. Because I wanted this configuration to be repeatable, I chose to create this file locally and then mount it to the Kind node at cluster creation time.&lt;&#x2F;p&gt;
&lt;p&gt;I fired up my text editor and smashed the following keys:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;git.benzo.test&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;host&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;git.benzo.test&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;capabilities&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;pull&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-array z-toml&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;resolve&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;skip_verify&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-language z-toml&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This config tells ContainerD, &lt;em&gt;&quot;Hey! There&#x27;s this server...you can pull and resolve container images there...but keep your eyes off my dodgy self-signed SSL certificate. It&#x27;s good, I promise.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The last thing I needed to do was to place that config file in the right location, via an additional modification to my Kind cluster definition:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; class=&quot;language-yaml z-code&quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;kind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;Cluster&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;kind.x-k8s.io&#x2F;v1alpha4&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;plaything&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerdConfigPatches&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-flow z-block-scalar z-literal z-yaml&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-modifier z-chomping-indicator z-yaml&quot;&gt;-&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;    [plugins.&amp;quot;io.containerd.grpc.v1.cri&amp;quot;.registry]
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;      config_path = &amp;quot;&#x2F;etc&#x2F;containerd&#x2F;certs.d&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-block z-yaml&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;nodes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;  &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;role&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;control-plane&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;extraMounts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hostPath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&#x2F;home&#x2F;ben&#x2F;code&#x2F;kind&#x2F;my-cr.toml&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerPath&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&#x2F;etc&#x2F;containerd&#x2F;certs.d&#x2F;git.benzo.test&#x2F;hosts.toml&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;    &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;extraPortMappings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;80&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hostPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;80&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;TCP&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;      &lt;span class=&quot;z-punctuation z-definition z-block z-sequence z-item z-yaml&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;443&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;hostPort&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-constant z-numeric z-integer z-decimal z-yaml&quot;&gt;443&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-yaml&quot;&gt;        &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-yaml&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-mapping z-yaml&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-unquoted z-plain z-out z-yaml&quot;&gt;TCP&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Focusing on the &lt;code&gt;extraMounts&lt;&#x2F;code&gt; section, I&#x27;m instructing Kind to take a file from my local filesystem (&lt;code&gt;hostPath&lt;&#x2F;code&gt;) and place it in a specific location on the Kubernetes node (&lt;code&gt;containerPath&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;With all that done, I spooled up my cluster with &lt;code&gt;just go&lt;&#x2F;code&gt;. Thankfully, I had configured all the deployments as ArgoCD applications, which meant that once ArgoCD was deployed, everything else I had previously configured and deployed just came back to life, without any additional command-line input from myself. The container images hosted in Forgejo pulled without any issues this time around.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;for-a-real-cluster&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#for-a-real-cluster&quot; aria-label=&quot;Anchor link for: for-a-real-cluster&quot;&gt;For a &lt;em&gt;Real&lt;&#x2F;em&gt; Cluster&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I would &lt;strong&gt;not&lt;&#x2F;strong&gt; recommend using the above &lt;code&gt;hosts.toml&lt;&#x2F;code&gt; for a production deployment. Blindly accepting a connection and trusting the SSL certificates can open you up to a number of exploits.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s quite common for enterprises to have their own SSL CA certificate and require it to be used for signing your Ingress SSL certs, instead of those you might get from a public CA like Let&#x27;s Encrypt.&lt;&#x2F;p&gt;
&lt;p&gt;For this scenario, I&#x27;d suggest creating:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A Secret
&lt;ul&gt;
&lt;li&gt;Containing the Client SSL certificate, which needs to be trusted by ContainerD&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;A ConfigMap containing a shell script to:
&lt;ul&gt;
&lt;li&gt;Modify the ContainerD &lt;code&gt;config.toml&lt;&#x2F;code&gt; if necessary&lt;&#x2F;li&gt;
&lt;li&gt;Copy over the SSL cert to a location on a Kuberneres Node&lt;&#x2F;li&gt;
&lt;li&gt;Create the required &lt;code&gt;hosts.toml&lt;&#x2F;code&gt; file (&lt;code&gt;echo &#x27;blah&#x27; &amp;gt; &#x2F;path&#x2F;to&#x2F;hosts.toml&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;A DaemonSet (Runs on each Node)
&lt;ul&gt;
&lt;li&gt;With the above Secret and ConfigMap mounted&lt;&#x2F;li&gt;
&lt;li&gt;Runs script defined in above ConfigMap&lt;&#x2F;li&gt;
&lt;li&gt;Note: You may need to configure the DaemonSet with &lt;code&gt;tolerations&lt;&#x2F;code&gt; if your nodes have &lt;code&gt;taints&lt;&#x2F;code&gt; (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;scheduling-eviction&#x2F;taint-and-toleration&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finally, I would be using a &lt;code&gt;hosts.toml&lt;&#x2F;code&gt; file that looks a little like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;toml&quot; class=&quot;language-toml z-code&quot;&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;hostname&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-tag z-table z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-table z-toml&quot;&gt;host&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-table z-toml&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;hostname&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-table z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;capabilities&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-array z-begin z-toml&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;pull&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-array z-toml&quot;&gt;,&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;resolve&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-array z-end z-toml&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-toml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-key z-toml&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-toml&quot;&gt;client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-definition z-key-value z-toml&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-basic z-toml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;path&#x2F;to&#x2F;cert.pem&lt;span class=&quot;z-punctuation z-definition z-string z-end z-toml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This file tells ContainerD, &lt;em&gt;&quot;Hey! There&#x27;s this server...you can pull and resolve container images there...it has an SSL certificate you might not know about but don&#x27;t worry, here&#x27;s a pem file you can use for validation.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The path to the &lt;code&gt;cert.pem&lt;&#x2F;code&gt; file can be relative to the &lt;code&gt;hosts.toml&lt;&#x2F;code&gt; file. I would recommend storing the certificate alongside the &lt;code&gt;hosts.toml&lt;&#x2F;code&gt; file, in the same directory, to keep things visible.&lt;&#x2F;p&gt;
&lt;p&gt;A little more reading on the use of this file can be &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containerd&#x2F;containerd&#x2F;blob&#x2F;main&#x2F;docs&#x2F;hosts.md&quot;&gt;found here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>WASM Will Be Your Backend</title>
          <pubDate>Fri, 21 Feb 2025 00:00:00 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/wasm-will-be-your-backend/</link>
          <guid>https://iambenzo.com/posts/wasm-will-be-your-backend/</guid>
          <description xml:base="https://iambenzo.com/posts/wasm-will-be-your-backend/">&lt;p&gt;For those of you who don&#x27;t know me too well, I&#x27;ve spent a lot of time around Kubernetes clusters. Managing Kubernetes clusters, writing applications for Kubernetes clusters, architecting solutions that centre around Kubernetes, planning my escape to a sun-bathed island with my own Kubernetes cluster in-hand...a fair bit of time.&lt;&#x2F;p&gt;
&lt;p&gt;A microservice architecture is typical for systems targeting a Kubernetes deployment - a number of loosely-coupled services which communicate frequently over the network, often via a message or event queue. The big reason for this is that Kubernetes can scale individual components of a system in response to a peak or trough of usage. &lt;em&gt;Why scale an entire application when only parts of it are under stress, right?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Not so long ago, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;blog&#x2F;2024&#x2F;12&#x2F;23&#x2F;navigating-platform-engineering-pitfalls-with-webassembly-components&#x2F;&quot;&gt;an article&lt;&#x2F;a&gt; made it&#x27;s way into my RSS reader about a CNCF sandbox project called &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wasmcloud.com&#x2F;docs&#x2F;intro&#x2F;&quot;&gt;wasmCloud&lt;&#x2F;a&gt;. On the surface, wasmCloud looks like an opinionated but robust way to design and deliver a microservice application architecture.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a Kubernetes-like orchestrator for applications that have been compiled to WASM binaries instead of Containers.&lt;&#x2F;p&gt;
&lt;p&gt;Without regurgitating the documentation, there&#x27;s components for your business logic, capabilities for pluggable functionality (such as messaging via Kafka) and interfaces for defining communication boundaries. As a bonus, you can link WASM runtimes via a &quot;lattice&quot;, which is a mesh built upon NATS.&lt;&#x2F;p&gt;
&lt;p&gt;wasmCloud looks like it may be a Kubernetes replacement, running WASM applications instead of Containers. Whilst very similar, in that it provides a level of application orchestration, it can harness a Kubernetes cluster to run WASM applications as well as Containers. You get the benefits of Kubernetes&#x27; hardware management &lt;em&gt;and&lt;&#x2F;em&gt; the features of wasmCloud.&lt;&#x2F;p&gt;
&lt;p&gt;wasmCloud doesn&#x27;t &lt;em&gt;need&lt;&#x2F;em&gt; a Kubernetes cluster to run though. It simply requires a WASM runtime to be installed on a host machine. This WASM runtime can be thought of as a JVM for Java applications, or a .NET runtime for dotnet applications. Thanks to this, the small binary size of WASM applications, and the NATS-based lattice, wasmCloud could be useful in edge computing scenarios - somewhere a Kubernetes deployment doesn&#x27;t particularly shine.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;containers-vs-wasm&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#containers-vs-wasm&quot; aria-label=&quot;Anchor link for: containers-vs-wasm&quot;&gt;Containers vs WASM&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;em&gt;Why would you use WASM instead of Containers?&lt;&#x2F;em&gt; - Well, let&#x27;s look at the similarities first:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Both are good options for polyglot dev teams, though WASM is a little more restrictive in programming language options.&lt;&#x2F;li&gt;
&lt;li&gt;Both can be stored in an OCI compatible registry for distribution.&lt;&#x2F;li&gt;
&lt;li&gt;Both enable applications to be run repeatably across multiple hosts.
&lt;ul&gt;
&lt;li&gt;Containers aren&#x27;t portable across CPU architectures though.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, some differences:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sandboxing
&lt;ul&gt;
&lt;li&gt;Containers run a stripped down OS.&lt;&#x2F;li&gt;
&lt;li&gt;WASM is purely application logic.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Startup Times
&lt;ul&gt;
&lt;li&gt;Containers take a few seconds to start running.&lt;&#x2F;li&gt;
&lt;li&gt;WASM applications can be running in under a second.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Multi-threading
&lt;ul&gt;
&lt;li&gt;Containers support mutli-threaded applications.&lt;&#x2F;li&gt;
&lt;li&gt;WASM applications are single-threaded but support asynchronous applications.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Attack Surface
&lt;ul&gt;
&lt;li&gt;For Containers, this depends on the Container OS and the host OS configuration.&lt;&#x2F;li&gt;
&lt;li&gt;WASM applications run in a sandbox, with protected memory.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The above are just some highlights which I find interesting, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wasmedge.org&#x2F;wasm_linux_container&#x2F;&quot;&gt;there&#x27;s more&lt;&#x2F;a&gt; to take a look at.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;digging-in&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#digging-in&quot; aria-label=&quot;Anchor link for: digging-in&quot;&gt;Digging In&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;After doing a some digging, I found an &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wasmCloud&#x2F;wasmCloud&#x2F;tree&#x2F;main&#x2F;examples&#x2F;rust&#x2F;composition&quot;&gt;example&lt;&#x2F;a&gt; of a Rust project for using wasmCloud. It looks a little convoluted.&lt;&#x2F;p&gt;
&lt;p&gt;There seems to be a swath of tooling required, that isn&#x27;t so visible in the project&#x27;s documentation right now. This can be remediated quickly through the bolstering of the project&#x27;s technical documentation, and through providing some tutorials that go below skin deep.&lt;&#x2F;p&gt;
&lt;p&gt;I think there&#x27;s an opportunity for refinement to improve the developer experience here. Taking a look at some programming language tooling, like the Cargo ecosystem may prove useful. The wasmCloud CLI could include the features of the WebAssembly Compositions CLI and the WASI Virt CLI, perhaps via a Cargo-like plugin system.&lt;&#x2F;p&gt;
&lt;p&gt;Looking a little further into the codebase, I notice that there&#x27;s a lot of &lt;code&gt;toml&lt;&#x2F;code&gt;, &lt;code&gt;yaml&lt;&#x2F;code&gt; and &lt;code&gt;wac&lt;&#x2F;code&gt; configuration files required for gluing everything together.&lt;&#x2F;p&gt;
&lt;p&gt;This takes me back to the days of writing Oracle SOA applications using SOAP, where you needed WSDL and XSD definitions for your components to work together - it wasn&#x27;t an experience that I particularly enjoyed as a developer but I do understand that, whilst verbose, it&#x27;s a way of defining and maintaining an explicit contract of communication.&lt;&#x2F;p&gt;
&lt;p&gt;For the various configuration files that are required, is there a generator available? One that may enable the generation of these files at compile time? My thinking for this would be around providing small language-specific libraries where a developer could implement an interface, or trait. Then the composition part could live in whatever the language&#x27;s equivalent of &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; is.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe a stupid question&#x2F;idea but there must be a way of consolidating them to reduce the number of steps required to get components communicating with each other.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;looking-forwards&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#looking-forwards&quot; aria-label=&quot;Anchor link for: looking-forwards&quot;&gt;Looking Forwards&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Whilst I feel there is room for improvement when it comes to the developer experience with wasmCloud, I do think that WASM + WASI has to be considered seriously for server-side workloads.&lt;&#x2F;p&gt;
&lt;p&gt;If your application doesn&#x27;t require multiple CPU threads, there&#x27;s too many benefits to choosing WASM over a Container: Smaller OCI artifacts &lt;a href=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;sustainability-starts-at-the-codebase&#x2F;&quot;&gt;have a large impact&lt;&#x2F;a&gt; on the sustainability of a solution, faster start-up times increase developer velocity and decrease scale-out times, application sandboxing reduces the surface of attack available to bad actors...&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t think that WASM will replace Containers entirely. But I believe we&#x27;ll certainly see a huge move towards WASM for a lot of use-cases server-side.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m certainly going to be keeping an eye on the wasmCloud, WASM and WASI projects.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Kindle to References</title>
          <pubDate>Thu, 28 Nov 2024 21:00:03 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/ktr/</link>
          <guid>https://iambenzo.com/posts/ktr/</guid>
          <description xml:base="https://iambenzo.com/posts/ktr/">&lt;h2 id=&quot;inspiration&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#inspiration&quot; aria-label=&quot;Anchor link for: inspiration&quot;&gt;Inspiration&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Recently, I started reading the enlightening &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;3VJoekN&quot;&gt;book by Bob Doto&lt;&#x2F;a&gt; on adopting the Zettelkasten methodology for capturing ideas and thinking creatively.&lt;&#x2F;p&gt;
&lt;p&gt;In the opening chapters, Bob describes the different types of notes you could take, one of them being reference notes.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Reference notes are single, long notes of brief citations or &quot;references&quot; to what caught your attention whilst reading a book, or consuming other forms of media.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I do the majority of my reading on my beloved  Kindle and, after reading the section of Bob&#x27;s book on reference notes, I wondered how I could optimally capture passages of interest from my Kindle and turn them into something tangible to revisit and store in my Zettelkasten.&lt;&#x2F;p&gt;
&lt;!-- The idea of switching focus from my book to a notepad or phone app to capture my thoughts presents me with an opportunity to lose focus through task switching. --&gt;
&lt;p&gt;I do appreciate that a notepad is sometimes best, as there&#x27;s a little cognitive magic that happens when we humans put pen to paper - but I&#x27;m using an electronic device for reading and I&#x27;m lazy enough to want to take advantage of that through some form of automation.&lt;&#x2F;p&gt;
&lt;p&gt;I shelved (virtually) Bob&#x27;s book to ponder.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stepping-through&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#stepping-through&quot; aria-label=&quot;Anchor link for: stepping-through&quot;&gt;Stepping Through&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Kindle has a feature that allows you to highlight passages of text as you&#x27;re reading. You can also add notes to these highlights whilst using the device.&lt;&#x2F;p&gt;
&lt;p&gt;These highlights and notes are stored on the Kindle in a plain text file found at: &lt;code&gt;&amp;lt;kindle_root&amp;gt;&#x2F;documents&#x2F;My Clippings.txt&lt;&#x2F;code&gt;. This file can be accessed by plugging the Kindle into your computer via USB.&lt;&#x2F;p&gt;
&lt;p&gt;We have a data source.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve opted to maintain a digital Zettelkasten under a fresh &quot;vault&quot; in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;obsidian.md&quot;&gt;Obsidian&lt;&#x2F;a&gt; - a program I&#x27;ve been using for quite some time for note taking, and my own personal [chaotic] brand of journalling.&lt;&#x2F;p&gt;
&lt;p&gt;Obsidian stores every note as a markdown file on your computer&#x27;s filesystem.&lt;&#x2F;p&gt;
&lt;p&gt;My thinking here was to find a way to parse the clippings file found on the Kindle and process it into a markdown file, which I can save to the part of my filesystem that is used by Obsidian.&lt;&#x2F;p&gt;
&lt;p&gt;Ideally the contents of the output would be uniform, conforming to some template that makes sense to me when revisiting the highlights and notes. Bob illustrates a potential format in his book, I decided to try and emulate that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enter-kindle-to-references-ktr&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#enter-kindle-to-references-ktr&quot; aria-label=&quot;Anchor link for: enter-kindle-to-references-ktr&quot;&gt;Enter Kindle to References (KTR)&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve created a small Command Line Interface (CLI) application, &quot;Kindle to References&quot; or KTR, to address my requirements.&lt;&#x2F;p&gt;
&lt;p&gt;I chose to write it in Rust because it&#x27;s a language I&#x27;ve been yearning to build something in for a little while, since going through &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-exercises.com&#x2F;100-exercises&#x2F;&quot;&gt;100 Exercises in Rust&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve had a wonderful experience with Rust, though you could argue that what I&#x27;ve built has almost no complexity to it and would be a simple creation in any language.&lt;&#x2F;p&gt;
&lt;p&gt;As a user of the CLI application, you supply the path to your clippings file and a path to an output directory. Hitting enter will result in a set of markdown files, one for each book you have highlights and&#x2F;or notes for, in your output directory.&lt;&#x2F;p&gt;
&lt;p&gt;These files can then be read by&#x2F;imported into Obsidian:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;ktr&#x2F;assets&#x2F;obsidian_output.png&quot; alt=&quot;Preview of output file format&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The above image shows an example of the output format in Obsidian. KTR&#x27;s default template will create a table listing the page number that a highlight was captured in.&lt;&#x2F;p&gt;
&lt;p&gt;The description column is where any related notes made on the Kindle will appear, or provide a space to add thoughts after reading a book. This column will always contain a footnote reference link to the highlighted content.&lt;&#x2F;p&gt;
&lt;p&gt;The final column will always be empty, no matter what you do on your Kindle - it&#x27;s a space intended for tagging and&#x2F;or linking thoughts to others in your Zettelkasten.&lt;&#x2F;p&gt;
&lt;p&gt;At the bottom of the page will be a numbered list of the highlighted content. These are the footnotes that are linked to in the table - Obsidian has a nice feature where you can hover your mouse over an internal link and a small window showing the content will pop up. I&#x27;ve tried to demonstrate that in the screenshot above - the mouse is missing, so you&#x27;ll have to take my word that I&#x27;m hovering it over the &lt;code&gt;[1]&lt;&#x2F;code&gt; link in the first row of the table.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst the application captures any notes that were added to highlights, I generally don&#x27;t take notes on my Kindle when highlighting text. This output file grants me an opportunity to revisit passages of text I found notable, add thoughts to them and also take advantage of Obsidian&#x27;s tagging functionality for linking references, thoughts and other notes together.&lt;&#x2F;p&gt;
&lt;p&gt;I feel that forcing myself to review the content I&#x27;ve highlighted might help embed my thoughts further - there&#x27;s no science behind that thinking though.&lt;&#x2F;p&gt;
&lt;p&gt;As a treat, you can optionally supply a path to a template of your own to alter the structure of the output files to your liking. I chose to use &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Keats&#x2F;tera&quot;&gt;Tera&lt;&#x2F;a&gt; as the template engine because &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;hachyderm.io&#x2F;@LGUG2Z&quot;&gt;@LGUG2Z&lt;&#x2F;a&gt; was raving about it to me on Mastodon.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;going-a-little-further&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#going-a-little-further&quot; aria-label=&quot;Anchor link for: going-a-little-further&quot;&gt;Going a Little Further&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I decided that the CLI wasn&#x27;t quite enough of a project and so built a Graphical User Interface (GUI) application too. It&#x27;s essentially a wizard style utility - &lt;em&gt;next, next, next...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;guide.elm-lang.org&#x2F;architecture&#x2F;&quot;&gt;ELM Architecture&lt;&#x2F;a&gt; was only something I had read about. Building this small application let me dip my toes into the heated pool of State, Messages, Update logic and View logic.&lt;&#x2F;p&gt;
&lt;p&gt;My application isn&#x27;t going to win any design or UX awards but it was fun to create. I got to dig into the (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;iced.rs&#x2F;&quot;&gt;Iced&lt;&#x2F;a&gt;) library&#x27;s documentation and source code to understand how things hang together, giving me experience of reading through a much more complicated Rust project. Again, I had a wonderful time.&lt;&#x2F;p&gt;
&lt;p&gt;The GUI application has an additional feature over the CLI - you can choose which books to process, rather than processing them all each time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;ktr&#x2F;assets&#x2F;ktr_gui_book_selection.png&quot; alt=&quot;KTR GUI Book Selection screenshot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Whether using the CLI, or the GUI - the end result is the same: A collection of one or more markdown files in an output directory - ready for use in Obsidian, or your favourite Markdown editor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;download-it-if-you-dare&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#download-it-if-you-dare&quot; aria-label=&quot;Anchor link for: download-it-if-you-dare&quot;&gt;Download It, If You Dare&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Obviously, I&#x27;ve built this tool for myself. I have chosen to make the code available &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iambenzo&#x2F;ktr&quot;&gt;over on my GitHub&lt;&#x2F;a&gt; though - just in case anyone else finds it useful too.&lt;&#x2F;p&gt;
&lt;p&gt;In the code repository, there are &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iambenzo&#x2F;ktr&#x2F;releases&#x2F;latest&quot;&gt;&lt;em&gt;unsigned&lt;&#x2F;em&gt; binaries available&lt;&#x2F;a&gt; for download. Your computer will likely complain about how untrustworthy I am as a developer, but you&#x27;re in control of your destiny, not your fancy calculator.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, now this has been created, I can go back to enjoying &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;3VJoekN&quot;&gt;Bob&#x27;s book&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Sustainability Starts at the Codebase</title>
          <pubDate>Sun, 04 Aug 2024 15:50:43 +0100</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/sustainability-starts-at-the-codebase/</link>
          <guid>https://iambenzo.com/posts/sustainability-starts-at-the-codebase/</guid>
          <description xml:base="https://iambenzo.com/posts/sustainability-starts-at-the-codebase/">&lt;h2 id=&quot;being-green&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#being-green&quot; aria-label=&quot;Anchor link for: being-green&quot;&gt;Being Green&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As Solution Architects in the modern world, we are charged with the responsibility of ensuring our solutions are sustainable, green, or environmentally friendly.&lt;&#x2F;p&gt;
&lt;p&gt;Doing so means that the data centres we use place less demand on the world&#x27;s precious resources for manufacturing the hardware that our solutions run on.&lt;&#x2F;p&gt;
&lt;p&gt;A typical area of focus is the use of &quot;green&quot; data centres. These green data centres often use energy-efficient cooling solutions, make use of renewable energy sources and may well have a hardware recycling&#x2F;re-purposing scheme.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not too difficult to achieve the use of green data centres in the cloud, the big three cloud providers all have &quot;green&quot; credentials &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;[1]&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;[2]&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;[3]&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Another area of focus is the efficient utilisation of physical resource through lifecycle management (assessment, maintenance, upgrades), resource optimisation (deploying infrastructure that meets workload requirements, rather than exceeds them) and virtualisation.&lt;&#x2F;p&gt;
&lt;p&gt;This second area of focus is where I&#x27;d like to spend some time with you today.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a plethora of tools which promise to help you optimise your infrastructure use. These tools usually work by spending some time monitoring the CPU and Memory usage of your applications and infrastructure utilisation before reporting back where you can reduce the compute.&lt;&#x2F;p&gt;
&lt;p&gt;Actioning the reported information results in a more energy and computationally efficient system (i.e. through a reduction of wasted CPU cycles) and, if you&#x27;re in the cloud, a more cost efficient system (i.e. through paying for less CPUs and Memory). &lt;em&gt;Rock and roll! Job done....right?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Well, if you&#x27;ve just completed a cloud migration with a load of monolithic applications, this might be the only thing you can do for now. But there&#x27;s more that &lt;em&gt;can&lt;&#x2F;em&gt; be done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-scenario&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-scenario&quot; aria-label=&quot;Anchor link for: a-scenario&quot;&gt;A Scenario&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s form a scenario where you have an existing monolithic application, written in Java, running in a Virtual Machine (VM) and are looking to break it up into smaller, containerised applications and deploy them to a Kubernetes cluster.&lt;&#x2F;p&gt;
&lt;p&gt;You and your team have already gone through defining your application boundaries and followed the domain driven design principals to the letter...&lt;em&gt;there&#x27;s a plan.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Naturally, as Java aficionados, you&#x27;ve selected Spring Boot as your framework of choice for the back-end API work. Hold the phone for just a moment - there&#x27;s an opportunity here to revisit the programming language used to craft your application&#x27;s new roots.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;m going to be picking on Java a little here, as I&#x27;ve seen it used extensively in an enterprise application developer environment - and it allows me to draw on my experiences.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;Why should I reconsider the programming language used?&quot;&lt;&#x2F;em&gt; I&#x27;m glad you asked. Let&#x27;s revisit the [abridged] Software Development Life Cycle (SDLC) a little...&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Developer writes code
&lt;ul&gt;
&lt;li&gt;Maybe pulling in additional third party dependencies, which may well be acquired via an internal artifact repository&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Developer pushes code to a remote code repository and creates a Pull Request (PR)&lt;&#x2F;li&gt;
&lt;li&gt;Continuous Integration (CI) pipeline kicks in
&lt;ul&gt;
&lt;li&gt;Builds application
&lt;ul&gt;
&lt;li&gt;Pulls third-party dependencies in the process&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Tests application&lt;&#x2F;li&gt;
&lt;li&gt;Pushes application build output to an artifact repository
&lt;ul&gt;
&lt;li&gt;Vulnerability scans run here&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Containerises application&lt;&#x2F;li&gt;
&lt;li&gt;Pushes application container to a container registry, ready for deployment
&lt;ul&gt;
&lt;li&gt;Vulnerability scans also run here&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Assuming all stages of the CI job passed and completed successfully, the developer&#x27;s PR can be merged and the updated application is then ready for deployment.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s break down the infrastructure used to complete this single cycle:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;Infrastructure&lt;&#x2F;th&gt;&lt;th&gt;Notes&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Developer writes code&lt;&#x2F;td&gt;&lt;td&gt;Storage, CPU, Memory&lt;&#x2F;td&gt;&lt;td&gt;For pulling dependencies from the self-hosted artifact repository&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Developer pushes code&lt;&#x2F;td&gt;&lt;td&gt;Storage, CPU, Memory&lt;&#x2F;td&gt;&lt;td&gt;Only if using a self-hosted source code repository&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;CI pipeline kicks in&lt;&#x2F;td&gt;&lt;td&gt;CPU, Memory&lt;&#x2F;td&gt;&lt;td&gt;Assuming self-hosted pipeline runners - billed in time if not&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Pushing to artifact repository&lt;&#x2F;td&gt;&lt;td&gt;Storage&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Pushing to container registry&lt;&#x2F;td&gt;&lt;td&gt;Storage&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;You can see that I’ve listed storage as key infrastructure here. Whilst it isn’t as expensive to purchase as computational resource, efficient use of storage means that less storage drives need to be provisioned in the data centre.&lt;&#x2F;p&gt;
&lt;p&gt;Another layer here is network. The source code, all of the application dependencies, the final application binary and the containerised application get transmitted over the network.&lt;&#x2F;p&gt;
&lt;p&gt;The size of data being transmitted at each stage of the CI process has bandwidth demands, which drives how much network infrastructure is required and used within the data centre - and how much bandwidth is available for other processes running simultaneously on the same network.&lt;&#x2F;p&gt;
&lt;p&gt;With our scenario in mind, the size of the application containers also impacts how quickly they can be retrieved from a container registry by a Kubernetes cluster at deployment time. This will have repercussions on the first startup time of your application.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully, you can see how optimising the storage space your applications demand reverberates through your infrastructure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;in-my-experience&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#in-my-experience&quot; aria-label=&quot;Anchor link for: in-my-experience&quot;&gt;In My Experience...&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Back to the question: &lt;em&gt;&quot;Why should I reconsider the programming language used?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At a previous job, I was generously granted some time to rewrite one of our Java REST APIs in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;&quot;&gt;GoLang&lt;&#x2F;a&gt;. The driver for this activity was to compare the performance characteristics of the two languages - and to appease my nagging. We&#x27;ll focus on the impact the experiment had on the infrastructure here though:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Language&lt;&#x2F;th&gt;&lt;th&gt;Number of Dependencies&lt;&#x2F;th&gt;&lt;th&gt;Binary Size&lt;&#x2F;th&gt;&lt;th&gt;Container Size&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Java (Spring Boot)&lt;&#x2F;td&gt;&lt;td&gt;142&lt;&#x2F;td&gt;&lt;td&gt;43MB&lt;&#x2F;td&gt;&lt;td&gt;130MB &lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;[4]&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GoLang&lt;&#x2F;td&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;8.3MB&lt;&#x2F;td&gt;&lt;td&gt;&lt;a href=&quot;&#x2F;posts&#x2F;tiny-golang-containers&quot;&gt;9.72MB&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Take a moment to consider how dramatic the difference in infrastructure usage these numbers imply.&lt;&#x2F;p&gt;
&lt;p&gt;Firstly, there are fewer third-party dependencies in the GoLang version because the application could be built almost completely using GoLang&#x27;s standard library - only reaching out to a third party for a database driver. This leads to a reduction in caching requirements for the artifact repository and also reduces the surface area for vulnerabilities in the codebase.&lt;&#x2F;p&gt;
&lt;p&gt;The GoLang binary size is over four times smaller than the Java equivalent. Again, this reduces the utilisation of the artifact repository and demands less bandwidth from the network in the transferring of the application binary.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, the GoLang application container is dramatically smaller than the Java application container. This reduces the storage capacity requirements for the container registry and reduces deployment time. Again, there&#x27;s less demand on the network in transferring the containerised application to and from the container registry.&lt;&#x2F;p&gt;
&lt;p&gt;Before this post becomes an advertisement for GoLang, I will quickly report that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Application binary and container had zero vulnerabilities&lt;&#x2F;li&gt;
&lt;li&gt;API response times reduced from multiple seconds to microseconds&lt;&#x2F;li&gt;
&lt;li&gt;Each instance of the application could handle significantly more customer requests before having to scale out horizontally&lt;&#x2F;li&gt;
&lt;li&gt;Scaling out was much faster because application start-up was near-instant (apposed to 20-30 seconds for Spring Boot)&lt;&#x2F;li&gt;
&lt;li&gt;The application used a fraction of the CPU and Memory at runtime&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The two versions of the application provided the exact same functionality - they were simply written in two different programming languages.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst I&#x27;ve largely focussed on the impact of storage and network usage so far, it&#x27;s important to note that the GoLang application also used less computational resource - CPU and Memory. This means that you can fit more applications into the same size of compute infrastructure, or look to reduce the size of that compute infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;I bet you can guess which version of the application made it through to production...and what language we adopted for new work.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine how different your infrastructure landscape would look after taking some time to evaluate the choice of programming language used in your applications. Maybe the components would be the same but they&#x27;d certainly be smaller in size. You&#x27;d be reducing the stress on your data centre, doing your bit for the planet &lt;em&gt;and&lt;&#x2F;em&gt; saving some money - all at the same time!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;going-forwards&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#going-forwards&quot; aria-label=&quot;Anchor link for: going-forwards&quot;&gt;Going Forwards&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Choosing a programming language is significantly easier to do when in a greenfield environment - where you&#x27;re creating new things from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;For brownfield environments, where you have existing applications, you could do something similar to me - take a small application and rewrite it as an experiment. Alternatively, the next time a new piece of development work presents itself, use that as an opportunity to assess how the application should be crafted.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst a new language can involve a learning process for your development teams, it&#x27;s also a growth opportunity for them. A chance to expand their skillset and look at their work from a fresh perspective.&lt;&#x2F;p&gt;
&lt;p&gt;Matthias Endler and Jeremy Soller discuss the introduction of a new programming language in depth on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;podcast&#x2F;s02e07-system76&#x2F;&quot;&gt;this episode&lt;&#x2F;a&gt; (about 1 hour in) of the wonderful &quot;Rust In Production&quot; Podcast - it&#x27;s clearly focused on introducing the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;Rust&lt;&#x2F;a&gt; programming language into an organisation but the concepts apply to any language you may be considering.&lt;&#x2F;p&gt;
&lt;p&gt;Have the conversation with your development team. Whilst a different programming language isn&#x27;t always viable, there may be options with your current programming language. With Java, you can reduce your application container size with &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.java&#x2F;learn&#x2F;jvm&#x2F;tools&#x2F;core&#x2F;jlink&#x2F;&quot;&gt;jlink&lt;&#x2F;a&gt;, or making use of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.graalvm.org&#x2F;&quot;&gt;GraalVM&lt;&#x2F;a&gt; native images.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-conclude&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#to-conclude&quot; aria-label=&quot;Anchor link for: to-conclude&quot;&gt;To Conclude&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Carefully considering the codebase has a rippling effect throughout your solution and can lead to more efficient use of your infrastructure. Efficient use of your infrastructure leads to a reduction in hardware needed in the data centres you use, and places less demand on the world&#x27;s precious resources which are used to manufacture that hardware.&lt;&#x2F;p&gt;
&lt;hr&gt;&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;azure.microsoft.com&#x2F;en-gb&#x2F;explore&#x2F;global-infrastructure&#x2F;sustainability&#x2F;&quot;&gt;Azure Sustainability&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;sustainability&#x2F;&quot;&gt;Amazon Web Services Sustainability&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;sustainability&#x2F;&quot;&gt;Google Cloud Sustainability&lt;&#x2F;a&gt; &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;The Java container requires the Java Runtime Environment for the application to run. We managed to reduce the size of the container image by over 100Mb through arduous use of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.java&#x2F;learn&#x2F;jvm&#x2F;tools&#x2F;core&#x2F;jlink&#x2F;&quot;&gt;jlink&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</description>
      </item>
      <item>
          <title>CLI: Just</title>
          <pubDate>Mon, 29 Apr 2024 09:36:26 +0100</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/cli-just/</link>
          <guid>https://iambenzo.com/posts/cli-just/</guid>
          <description xml:base="https://iambenzo.com/posts/cli-just/">&lt;p&gt;I&#x27;m getting older. My memory and my wrists aren&#x27;t as nimble as they once were.&lt;&#x2F;p&gt;
&lt;p&gt;When I do get a sliver of time to work on a personal project, it&#x27;s nice to have a couple of project specific one-liners that I can run in my terminal to save me from the inevitable chore of re-reading the documentation of whatever build tool or process I want to use.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;just.systems&#x2F;&quot;&gt;Just&lt;&#x2F;a&gt; is a tool that supplements my aging brain wonderfully. It&#x27;s essentially a command runner in the guise of a Makefile.&lt;&#x2F;p&gt;
&lt;p&gt;All I have to do is craft a small &lt;code&gt;.justfile&lt;&#x2F;code&gt; in the root directory of a project, whilst the commands are all fresh in my mind. When I finally return to my project, I smash &lt;code&gt;just -l&lt;&#x2F;code&gt; into my terminal and I&#x27;ll be welcomed by a list of actions I can execute, based on the project I&#x27;m in.&lt;&#x2F;p&gt;
&lt;p&gt;Take this blog, for example. Do I remember the &lt;code&gt;hugo new content…&lt;&#x2F;code&gt; command each year I pressure myself into writing a new blog post? &lt;em&gt;Hell no!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I have a &lt;code&gt;.justfile&lt;&#x2F;code&gt; for my blog, and after checking my usual actions with &lt;code&gt;just&lt;&#x2F;code&gt; (no &lt;code&gt;-l&lt;&#x2F;code&gt; needed for me, you&#x27;ll see why), I&#x27;m reminded that I can run &lt;code&gt;just post&lt;&#x2F;code&gt; followed by a post title to create a new blog post and open it in a text editor.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s my blog&#x27;s &lt;code&gt;.justfile&lt;&#x2F;code&gt; in all its glory:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;make&quot; class=&quot;language-make z-code&quot;&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; `just` override
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;_default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;just&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; Serve the site on localhost
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;serve&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;hugo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; serve&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; Create a new blog post (titles-like-this)
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;post title&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;hugo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; new content posts&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;title&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;p&lt;&#x2F;span&gt; .&#x2F;content&#x2F;posts&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;title&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;assets&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; .&#x2F;content&#x2F;posts&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;title&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.md .&#x2F;content&#x2F;posts&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;title&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;index.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;hx&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; .&#x2F;content&#x2F;posts&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;title&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&#x2F;index.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; Start a tmux session
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; new&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;Pd&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;s&lt;&#x2F;span&gt; blog&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;n&lt;&#x2F;span&gt; code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; neww&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;Pd&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; blog&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;F&lt;&#x2F;span&gt; 2&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;n&lt;&#x2F;span&gt; serve&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; send-keys&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; blog:2 &lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;just serve&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; Enter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;firefox&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; http:&#x2F;&#x2F;localhost:1313&#x2F;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-logical z-job z-shell&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;tmux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; attach&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; blog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, there are four recipes, or actions as I sometimes call them. The &lt;code&gt;_default&lt;&#x2F;code&gt; recipe means that I can use the &lt;code&gt;just&lt;&#x2F;code&gt; command without the &lt;code&gt;-l&lt;&#x2F;code&gt; to list my available actions. The &lt;code&gt;serve&lt;&#x2F;code&gt; recipe simply gets my website running locally.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;post&lt;&#x2F;code&gt; recipe creates a new blog entry with a title that I provide at invocation (&lt;code&gt;just post super-sexy-catchy-post-title&lt;&#x2F;code&gt;), wrangles that post into the directory structure that I like and then opens that new post in my text editor of the day.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, the &lt;code&gt;tmux&lt;&#x2F;code&gt; recipe spawns a new tmux session with two windows - one for activities and one for serving my website locally. It also cracks open a browser window, loading the locally hosted instance of my site. This is useful for when I might decide to work on my theme or site functionality.&lt;&#x2F;p&gt;
&lt;p&gt;Using this tool allows me to start being productive quickly, with less typing - saving my poor wrists from extraneous fatigue.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example of a &lt;code&gt;.justfile&lt;&#x2F;code&gt; that I might use for in a directory that contains a number of dockerfiles:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;make&quot; class=&quot;language-make z-code&quot;&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; Variables for defaults
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-variable z-other z-makefile&quot;&gt;defaultFile&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-string z-makefile&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-makefile&quot;&gt;&amp;#39;bestOne&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; `just` override
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;_default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;just&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; Build a dockerfile
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;build file=defaultFile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt;
&lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; build&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;f&lt;&#x2F;span&gt; .&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;.dockerfile&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:taaaag .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; Build and run a dockerfile
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;run file=defaultFile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-makefile&quot;&gt;(build file)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; run&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;rm&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:taaaag&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; (Hidden) Build and Tag container image
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;_tag version file=defaultFile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-makefile&quot;&gt;(build file)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; tag &lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:taaaag container-registry.com&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;version&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment z-line z-number-sign z-makefile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-makefile&quot;&gt;#&lt;&#x2F;span&gt; Build, Tag and Push a container image
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-makefile&quot;&gt;&lt;span class=&quot;z-entity z-name z-function z-makefile&quot;&gt;publish version file=defaultFile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-makefile&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-function z-arguments z-makefile&quot;&gt;&lt;span class=&quot;z-string z-unquoted z-makefile&quot;&gt;(_tag version file)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;    &lt;span class=&quot;z-source z-shell&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; push container-registry.com&#x2F;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;file&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;:&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-group z-expansion z-brace z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-begin z-shell&quot;&gt;{&lt;&#x2F;span&gt;version&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-expansion z-brace z-end z-shell&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-makefile&quot;&gt;&lt;span class=&quot;z-meta z-function z-body z-makefile&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This one&#x27;s a little more complex but it shows how you can chain recipes together. For example, the &lt;code&gt;run&lt;&#x2F;code&gt; recipe will first run the &lt;code&gt;build&lt;&#x2F;code&gt; recipe.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t go into much more detail here - hopefully you see how I find this utility useful. If you&#x27;re interested in checking &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;casey&#x2F;just&quot;&gt;Just&lt;&#x2F;a&gt; out, it&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;just.systems&#x2F;man&#x2F;en&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt; is pretty thorough.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>My Favourite Card Game</title>
          <pubDate>Mon, 22 Apr 2024 13:47:09 +0100</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/my-favourite-card-game/</link>
          <guid>https://iambenzo.com/posts/my-favourite-card-game/</guid>
          <description xml:base="https://iambenzo.com/posts/my-favourite-card-game/">&lt;p&gt;I used to travel a lot for work, and got into the habit of carrying around a pack of playing cards - for downtime at a bar, or when stuck waiting out yet another train cancellation. The playing cards have seen plenty of daylight at home and during family gatherings too!&lt;&#x2F;p&gt;
&lt;p&gt;The card game I’m about to tell you about has to be my favourite. I won’t disclose what I call the game - it’s a naughty word - but I will share how to play the game because I’ve had so much fun with it over the years.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Seven Minute Rule</title>
          <pubDate>Fri, 14 Jan 2022 16:52:40 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/seven-minute-rule/</link>
          <guid>https://iambenzo.com/posts/seven-minute-rule/</guid>
          <description xml:base="https://iambenzo.com/posts/seven-minute-rule/">&lt;p&gt;I value my time.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst working, delivering is the top priority for me and anything that detracts from that could be a hindrance.&lt;&#x2F;p&gt;
&lt;p&gt;I work hard to enusure that I&#x27;m not in meetings where I won&#x27;t be in a position to add value, or where the meeting is of no value to me.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Tiny Golang Containers</title>
          <pubDate>Thu, 18 Nov 2021 10:54:24 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/tiny-golang-containers/</link>
          <guid>https://iambenzo.com/posts/tiny-golang-containers/</guid>
          <description xml:base="https://iambenzo.com/posts/tiny-golang-containers/">&lt;p&gt;Over this year, I&#x27;ve slowly become more Golang oriented as a developer and I&#x27;m really enjoying the journey that choice is taking me on.&lt;&#x2F;p&gt;
&lt;p&gt;Traditionally, I&#x27;ve built web services with Spring Boot and Java but more recently, I&#x27;ve noticed there are a number of benefits to developing such services with Golang and it&#x27;s standard library: Lower runtime resource requirements and no runtime environment required to name a few.&lt;&#x2F;p&gt;
&lt;p&gt;Another benefit I&#x27;d like to discuss here is achieving &lt;em&gt;tiny&lt;&#x2F;em&gt; containerized applications with Golang.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why&quot; aria-label=&quot;Anchor link for: why&quot;&gt;Why?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The main advantages of creating container images which are small in size are that they:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Require less storage space in a container registry&lt;&#x2F;li&gt;
&lt;li&gt;Require less bandwidth for upload and download&lt;&#x2F;li&gt;
&lt;li&gt;Require less available disk in runtime environment (e.g Kubernetes)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The above points typically keep cloud subscriptions costs down and, in extension, your product team happy 🙂&lt;&#x2F;p&gt;
&lt;p&gt;Another key advantage to stripping down container images to their absolute bare necessities is that it reduces that container&#x27;s surface area for exploitation - meaning safer deployments too.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how&quot; aria-label=&quot;Anchor link for: how&quot;&gt;How?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;sample-application&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sample-application&quot; aria-label=&quot;Anchor link for: sample-application&quot;&gt;Sample Application&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;To show how to create slender containers with Golang, we need a sample application to containerize, so I created one: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iambenzo&#x2F;dirtyhttp-example&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;iambenzo&#x2F;dirtyhttp-example&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a simple web service, which exposes an in-memory data structure for the storing and retrieval of user information via HTTP request. (Only around 200 lines of code, including spacing and comments if you want to check it out)&lt;&#x2F;p&gt;
&lt;p&gt;Usage instructions are included in the README file.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;full-fat-container&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#full-fat-container&quot; aria-label=&quot;Anchor link for: full-fat-container&quot;&gt;Full Fat Container&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;In the same way some of us struggle to digest full fat milk, our container registries would eventually become bloated with full fat containers.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s see how much damage a creamy Golang container with all the bells and whistles does:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;dockerfile&quot; class=&quot;language-dockerfile z-code&quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Use Alpine for its small footprint
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; golang:&lt;span class=&quot;z-entity z-name z-enum z-tag-digest&quot;&gt;alpine&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&#x2F;app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Download our dependencies
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; go.mod .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; go.sum .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;go mod download
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Build the application binary
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; *.go .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;go build -o &#x2F;dirtyhttp-example
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;EXPOSE &lt;&#x2F;span&gt;8080
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-dockerfile&quot;&gt;CMD &lt;&#x2F;span&gt;[ &lt;span class=&quot;z-string z-quoted z-double z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;dirtyhttp-example&lt;span class=&quot;z-punctuation z-definition z-string z-end z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; ]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The command to build the container locally is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; build&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; go-example:fat&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;f&lt;&#x2F;span&gt; Dockerfile.fat .&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once docker has finished working it&#x27;s magic, we&#x27;ll have a container that looks like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;tiny-golang-containers&#x2F;img&#x2F;full-fat.png&quot; alt=&quot;Full Fat&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can see above that our &quot;fat&quot; container image requires a meaty 398MB of storage space.&lt;&#x2F;p&gt;
&lt;p&gt;To run the container image, you&#x27;d use the following command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; run&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;rm&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;p&lt;&#x2F;span&gt; 8080:8080 go-example:fat&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;going-semi-skimmed&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#going-semi-skimmed&quot; aria-label=&quot;Anchor link for: going-semi-skimmed&quot;&gt;Going Semi-Skimmed&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The wonderful developers at Google have made a &quot;runtime&quot; container available to eliminate some of the bloat in our previous container.&lt;&#x2F;p&gt;
&lt;p&gt;To use it properly, we need to make use of a multi-stage build. This is where we use one [intermediary] docker image to build our application and send the output binary to a slimmed down image where the application will actually run.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;dockerfile&quot; class=&quot;language-dockerfile z-code&quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Build
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; golang:&lt;span class=&quot;z-entity z-name z-enum z-tag-digest&quot;&gt;1.16-buster&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;AS&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-stage-name&quot;&gt;build&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&#x2F;app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; go.mod .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; go.sum .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;go mod download
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; *.go .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;go build -o &#x2F;dirtyhttp-example
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Runtime
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; gcr.io&#x2F;distroless&#x2F;base-debian10
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; --from=&lt;span class=&quot;z-variable z-stage-name&quot;&gt;build&lt;&#x2F;span&gt; &#x2F;dirtyhttp-example &#x2F;dirtyhttp-example
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;EXPOSE &lt;&#x2F;span&gt;8080
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;USER &lt;&#x2F;span&gt;nonroot:nonroot
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-dockerfile&quot;&gt;ENTRYPOINT &lt;&#x2F;span&gt;[&lt;span class=&quot;z-string z-quoted z-double z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;dirtyhttp-example&lt;span class=&quot;z-punctuation z-definition z-string z-end z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output container image in the above scenario is the second [runtime] one, based on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;gcr.io&#x2F;distroless&#x2F;base-debian10&quot;&gt;gcr.io&#x2F;distroless&#x2F;base-debian10&lt;&#x2F;a&gt; , where the only addition to that image is the application binary which was built in a full-fat Golang image. Let&#x27;s build it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; build&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; go-example:semi&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;f&lt;&#x2F;span&gt; Dockerfile.semi .&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;tiny-golang-containers&#x2F;img&#x2F;semi-skimmed.png&quot; alt=&quot;Semi-Skimmed&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &quot;semi&quot; version of our container image is already significantly smaller - 26.6MB! This is just under 15 times smaller than our previous &quot;fat&quot; version.&lt;&#x2F;p&gt;
&lt;p&gt;To run the container image, you&#x27;d use the following command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; run&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;rm&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;p&lt;&#x2F;span&gt; 8080:8080 go-example:semi&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-magic-soya-bean&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-magic-soya-bean&quot; aria-label=&quot;Anchor link for: the-magic-soya-bean&quot;&gt;The Magic Soya Bean&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;re at a good size now that we&#x27;re utilising Google&#x27;s stripped-out runtime base image - but we can go even further.&lt;&#x2F;p&gt;
&lt;p&gt;Because we know our codebase is pure Golang code and doesn&#x27;t depend on any C code, we can build a statically linked binary in our stage-one (build) image and use the smallest base image available - scratch - as the base image our stage-two (runtime) image:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;dockerfile&quot; class=&quot;language-dockerfile z-code&quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Builder image
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; golang:&lt;span class=&quot;z-entity z-name z-enum z-tag-digest&quot;&gt;alpine&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;AS&lt;&#x2F;span&gt; &lt;span class=&quot;z-variable z-stage-name&quot;&gt;build&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;apk update &amp;amp;&amp;amp; apk add --no-cache ca-certificates &amp;amp;&amp;amp; update-ca-certificates
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&#x2F;app
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Download our dependencies
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; go.mod .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; go.sum .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;go mod download
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; *.go .&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Build a statically linked binary
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;RUN &lt;&#x2F;span&gt;CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o &#x2F;dirtyhttp-example
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-comment z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-dockerfile&quot;&gt;#&lt;&#x2F;span&gt; Super small runtime base image
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;FROM&lt;&#x2F;span&gt; scratch
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; --from=&lt;span class=&quot;z-variable z-stage-name&quot;&gt;build&lt;&#x2F;span&gt; &#x2F;etc&#x2F;ssl&#x2F;certs&#x2F;ca-certificates.crt &#x2F;etc&#x2F;ssl&#x2F;certs&#x2F;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;COPY&lt;&#x2F;span&gt; --from=&lt;span class=&quot;z-variable z-stage-name&quot;&gt;build&lt;&#x2F;span&gt; &#x2F;dirtyhttp-example &#x2F;dirtyhttp-example
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-control z-dockerfile&quot;&gt;EXPOSE &lt;&#x2F;span&gt;8080
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-dockerfile&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-dockerfile&quot;&gt;ENTRYPOINT &lt;&#x2F;span&gt;[&lt;span class=&quot;z-string z-quoted z-double z-dockerfile&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;dirtyhttp-example&lt;span class=&quot;z-punctuation z-definition z-string z-end z-dockerfile&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s quickly go over the fancy adjustments to the build step:&lt;&#x2F;p&gt;
&lt;p&gt;First, &lt;code&gt;CGO_ENABLED=0&lt;&#x2F;code&gt; disables the C interoperability and is the part of the command that means we build a binary that&#x27;s been statically linked with any libraries we use.&lt;&#x2F;p&gt;
&lt;p&gt;Next, &lt;code&gt;GOOS=linux&lt;&#x2F;code&gt; tells the build command that we&#x27;re building a binary for the linux platform.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;-a&lt;&#x2F;code&gt; flag forces the rebuilding of all packages, even if they&#x27;re up-to-date.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, the &lt;code&gt;-installsuffix&lt;&#x2F;code&gt; flag simply separates the current build output from any default build output in the package installation directory.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we&#x27;ve covered that off, let&#x27;s see how the container image looks:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; build&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;t&lt;&#x2F;span&gt; go-example:soya&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;f&lt;&#x2F;span&gt; Dockerfile.soya .&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;tiny-golang-containers&#x2F;img&#x2F;soya.png&quot; alt=&quot;Soya Bean&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve achieved an even slimmer container image - 6.83MB! Our &quot;soya&quot; image is just under 4 times smaller than our semi-skimmed image and a massive 58 times smaller than our full fat image!&lt;&#x2F;p&gt;
&lt;p&gt;To run the container image, you&#x27;d use the following command:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash z-code&quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt; &lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; run&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;it&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; --&lt;&#x2F;span&gt;rm&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-option z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-parameter z-shell&quot;&gt; -&lt;&#x2F;span&gt;p&lt;&#x2F;span&gt; 8080:8080 go-example:soya&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;summary&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;Summary&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Typically, container registry SKUs place limits on storage space, image upload bandwidth and image download bandwidth. Increasing, or surpassing those limits costs cash money.&lt;&#x2F;p&gt;
&lt;p&gt;With that in mind, it&#x27;s our duty as penny-pinching product teams to ensure that our container images are as small as possible.&lt;&#x2F;p&gt;
&lt;p&gt;Taking advantage of multi-stage container builds has a huge impact on container image size - a step that should be taken regardless of programming language.&lt;&#x2F;p&gt;
&lt;p&gt;With Golang, we&#x27;ve been able to take the multi-stage build one step further by building a binary that will run on a &lt;code&gt;FROM scratch&lt;&#x2F;code&gt; base image. I can imagine that this could be applicable to any compiled language that doesn&#x27;t need a runtime (C++, Rust, etc).&lt;&#x2F;p&gt;
&lt;p&gt;I know that Spring Native is in beta right now - once it&#x27;s out of beta, I&#x27;d love to see if comparable image sizes can be built with Java.&lt;&#x2F;p&gt;
&lt;p&gt;With containers this small, it&#x27;d be a while before you start paying more for your platform!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>CQRS Helps Me Eat Without Distraction</title>
          <pubDate>Wed, 07 Oct 2020 00:00:00 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/cqrs-helps-me-eat-without-distraction/</link>
          <guid>https://iambenzo.com/posts/cqrs-helps-me-eat-without-distraction/</guid>
          <description xml:base="https://iambenzo.com/posts/cqrs-helps-me-eat-without-distraction/">&lt;p&gt;Let&#x27;s ask the most important question anyone worth knowing can be asked: How many chicken nuggets can I eat in 3 minutes?&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Boat Inspired Microservice Resilience</title>
          <pubDate>Thu, 30 Apr 2020 00:00:00 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/microservice-resillience/</link>
          <guid>https://iambenzo.com/posts/microservice-resillience/</guid>
          <description xml:base="https://iambenzo.com/posts/microservice-resillience/">&lt;p&gt;It&#x27;s pretty normal for you to want to have a stable system.&lt;&#x2F;p&gt;
&lt;p&gt;What happens though, when parts of your system depend upon other 3rd party systems? What happens, when your cloud provider lumps you with a network that sometimes decides to disable itself, where the only fix is to give them even more money?&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Answer: Design and build with resilience in mind.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;designing-for-known-failures&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#designing-for-known-failures&quot; aria-label=&quot;Anchor link for: designing-for-known-failures&quot;&gt;Designing For Known Failures&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We can start by simply digging into our experience pool to unearth some of the obstacles we may have previously encountered - there&#x27;s nothing new under the sun and a problem you&#x27;ve previously had is likely to be a problem you will experience again. Are any of your historic solutions applicable in your new, or current system?&lt;&#x2F;p&gt;
&lt;p&gt;Architect away from single points of failure when designing your system - ensure the ability to provide redundancy for each of our system&#x27;s components and also the ability to easily scale out.&lt;&#x2F;p&gt;
&lt;p&gt;When designing your system, you can consider the Bulkhead Design Pattern:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bulkheads&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#bulkheads&quot; aria-label=&quot;Anchor link for: bulkheads&quot;&gt;Bulkheads&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Bulkheads are used to seal off parts of boats and ships to prevent sinking.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;upload.wikimedia.org&#x2F;wikipedia&#x2F;commons&#x2F;e&#x2F;e8&#x2F;Compartments_and_watertight_subdivision_of_a_ship%27s_hull_%28Seaman%27s_Pocket-Book%2C_1943%29.jpg&quot; alt=&quot;Bulkhead&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As a pattern in Microservice Architecture, it&#x27;s a way of sealing off failure and avoid cascading failure (one failure leading to many more failures in the same part, and other parts of a system).&lt;&#x2F;p&gt;
&lt;p&gt;The core concept here, is to separate out your components in a way where one failure doesn&#x27;t impact the whole system and ensure degraded functionality when part of the system goes down.&lt;&#x2F;p&gt;
&lt;p&gt;Degraded functionality is a term to express that a piece of functionality may gracefully disappear or be partially complete.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;okay-so&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#okay-so&quot; aria-label=&quot;Anchor link for: okay-so&quot;&gt;Okay, so...&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;You can start by thinking about how you might want to divide your system up.&lt;&#x2F;p&gt;
&lt;p&gt;The whole Microservice Architecture ethos lends itself to this pattern quite naturally - small, isolated services, each with their own data stores that can only be accessed via that service.&lt;&#x2F;p&gt;
&lt;p&gt;To take that further, you can consider a service&#x27;s criticality - you don&#x27;t want a high volume, low critical service bombarding a message queue and hindering a highly critical and perhaps low volume service from functioning correctly.&lt;&#x2F;p&gt;
&lt;p&gt;In that scenario, you&#x27;d provide your critical service dedicated resources, like it&#x27;s own message queue to stop it&#x27;s functionality being impacted by less important stuff. This can be applied to any shared resource, like a database which could be split into several databases as needed.&lt;&#x2F;p&gt;
&lt;p&gt;Microservices suit horizontal scaling well - essentially running multiple instances of a service in order to meet demand.&lt;&#x2F;p&gt;
&lt;p&gt;The use of Load Balancers will stop any incoming calls being directed to a misbehaving instance of a service, isolating that service from use until it returns to functioning order.&lt;&#x2F;p&gt;
&lt;p&gt;We can also reject incoming calls to a service when that service is at maximum capacity - this is called Load Shedding.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, we can make sure we use the &lt;a href=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;microservice-resillience&#x2F;#circuit-breakers&quot;&gt;Circuit Breaker Pattern&lt;&#x2F;a&gt; on all synchronous 3rd party (upstream) calls - we&#x27;ll dive into what that means momentarily.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;embracing-failure&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#embracing-failure&quot; aria-label=&quot;Anchor link for: embracing-failure&quot;&gt;Embracing Failure&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Things go wrong. That upstream service might not be accepting calls right now. Your DNS service might be trying to take today off as annual leave.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst we now have a pattern to feed into our architecture, there are three patterns that work hand-in-hand within our components to help mitigate complete system meltdown: Timeouts, Retries and Circuit Breakers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;microservice-resillience&#x2F;img&#x2F;circuit-breaker.png&quot; alt=&quot;Circuit Breaker Pattern&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;timeouts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#timeouts&quot; aria-label=&quot;Anchor link for: timeouts&quot;&gt;Timeouts&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;If you spent any time interacting with the world-wide web, you&#x27;ve come across a timeout error before. It means that your browser has become fed up with waiting for data from the website you&#x27;re trying to access.&lt;&#x2F;p&gt;
&lt;p&gt;You can define how long your services wait for outgoing calls to complete and then what to do in the event that a call does take too long. This means you can avoid cascading failures by handling timeouts with default, or degraded functionality. Timeouts alone only &lt;em&gt;reduces&lt;&#x2F;em&gt; the risk of a service running out of threads to work on though - it&#x27;ll still be accepting and trying to handle incoming requests.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;retries&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#retries&quot; aria-label=&quot;Anchor link for: retries&quot;&gt;Retries&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Timeouts are typically used in conjunction with a Retry strategy - which are ideal for combating those transient faults, where there might be a momentary loss of connectivity. Usually, you&#x27;ll attempt to retry a call either straight away, or after a pre-determined amount of time. After a small number of retries, you should hook back into your timeout handling logic for default or degraded functionality.&lt;&#x2F;p&gt;
&lt;p&gt;Please make sure that you log &lt;strong&gt;all&lt;&#x2F;strong&gt; retry attempts, it&#x27;ll make your life much easier when you perform any tracing.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;circuit-breakers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#circuit-breakers&quot; aria-label=&quot;Anchor link for: circuit-breakers&quot;&gt;Circuit Breakers&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Finally, you can tie both Timeouts and Retries with the Circuit Breaker pattern to not only eliminate cascading failure but also avoid having your services run out of threads.&lt;&#x2F;p&gt;
&lt;p&gt;A circuit breaker monitors your outgoing calls for any timeouts or errors and trips when a defined failure threshold is reached.&lt;&#x2F;p&gt;
&lt;p&gt;When tripped, your circuit breaker is &#x27;open&#x27; and will return an error, or a default response on behalf of the upstream service without actually calling that upstream service - wave goodbye to further timeouts and hello to thread availability.&lt;&#x2F;p&gt;
&lt;p&gt;After some time, the circuit breaker will go into a &#x27;half-open&#x27; state and attempt to reconnect with the upstream service. If successful, the circuit breaker will &#x27;close&#x27; up and everything will return to functioning as designed. If unsuccessful, the circuit breaker will remain &#x27;open&#x27; and attempt to open up a little later.&lt;&#x2F;p&gt;
&lt;p&gt;You can write your own circuit breaker using the many open source examples out there - make sure it&#x27;s thread safe and at least has a configurable failure threshold and open state duration. There are 3rd party libraries kicking around, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;resilience4j&#x2F;resilience4j&quot;&gt;Resilience4J&lt;&#x2F;a&gt; is one I&#x27;ve come across for Java developers.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s important to log your circuit breaker state changes for tracing too.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;degrading-and-defaulting-functionality&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#degrading-and-defaulting-functionality&quot; aria-label=&quot;Anchor link for: degrading-and-defaulting-functionality&quot;&gt;Degrading and Defaulting Functionality&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If we&#x27;re going to fail, we should fail as fast as we can, to at least remain responsive to our users. Even though we can&#x27;t always avoid sending an error message back to our caller, we should attempt providing degraded or default functionality first.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ve already explained that degrading functionality is a term to express that a piece of functionality may gracefully disappear or be partially complete. The circuit breaker pattern allows for this partial shift in functionality.&lt;&#x2F;p&gt;
&lt;p&gt;An example of degraded functionality is when an advertisement service is unable to return data to a website. After a circuit breaker trips, the degraded functionality could mean that adverts aren&#x27;t displayed until the advertisement service starts working again.&lt;&#x2F;p&gt;
&lt;p&gt;Default functionality is what you provide when all else fails. Normally this will be some data from a cache or, if we must, an error message.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fin&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fin&quot; aria-label=&quot;Anchor link for: fin&quot;&gt;Fin&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Thank you for reading this post, I know it&#x27;s a long one for me.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully, you&#x27;ve found it useful - if you have any thoughts or opinions on the content in this post, please do reach out to me in the comments section below.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Maven Archetypes</title>
          <pubDate>Wed, 25 Mar 2020 00:00:00 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/maven-archetypes/</link>
          <guid>https://iambenzo.com/posts/maven-archetypes/</guid>
          <description xml:base="https://iambenzo.com/posts/maven-archetypes/">&lt;p&gt;I don&#x27;t know where you stand on the raging war between Gradle and Maven for build tool of choice for Java developers but one thing that keeps me using Maven is that it has core functionality for archetypes.&lt;&#x2F;p&gt;
&lt;p&gt;An archetype is a templated project that has configurable options available for a user of the archetype. When you use an archetype, you plug in the options made available to you and a few moments later, a project based on that archetype and your parameters has been generated for you.&lt;&#x2F;p&gt;
&lt;p&gt;This has great advantages in an entity based API delivery - where you&#x27;re interacting with a single entity (e.g. products or customers) per service. Typically for these services, you&#x27;re exposing CRUD operations with small amounts of business logic and they contain a lot of boilerplate code.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine that, with a single command, all of your boilerplate code is taken care of and that you just need to focus on adding fields to your entity and business logic - lovely!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-archetype&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-to-archetype&quot; aria-label=&quot;Anchor link for: how-to-archetype&quot;&gt;How to Archetype&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;generation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#generation&quot; aria-label=&quot;Anchor link for: generation&quot;&gt;Generation&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Here, I&#x27;ll show you some of the archetype features I&#x27;ve used and provide a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iambenzo&#x2F;maven-archetype-example&quot;&gt;sample archetype&lt;&#x2F;a&gt; for you to go through and&#x2F;or use.&lt;&#x2F;p&gt;
&lt;p&gt;The easiest way to get going, is to create a project exactly as you normally would. When you&#x27;re done, navigate to the project&#x27;s base directory and enter the following in a terminal:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mvn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; archetype:create-from-project&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will create an archetype from your current project. This archetype will be found in &lt;code&gt;&#x2F;target&#x2F;generated-sources&#x2F;archetype&lt;&#x2F;code&gt;. I would advise taking a copy of this directory to work on in another part of your filesystem.&lt;&#x2F;p&gt;
&lt;p&gt;Take a brief moment to look at the &lt;code&gt;pom.xml&lt;&#x2F;code&gt; in the archetype project root directory. Edit as you like.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we have the base archetype, it&#x27;s time to start adding parameters to it. These parameters will be used to replace parts of your code and filenames with user-specified values, when they use your archetype.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;adding-parameters&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#adding-parameters&quot; aria-label=&quot;Anchor link for: adding-parameters&quot;&gt;Adding Parameters&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;First we need to define what parameters should be made available. This is done in the &lt;code&gt;src&#x2F;main&#x2F;resources&#x2F;META-INF&#x2F;maven&#x2F;archetype-metadata.xml&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;p&gt;There are some properties made available to us without any configuration but any custom properties should be defined in a &lt;code&gt;&amp;lt;requiredProperties&amp;gt;&amp;lt;&#x2F;requiredProperties&amp;gt;&lt;&#x2F;code&gt; block like so:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;xml&quot; class=&quot;language-xml z-code&quot;&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperties&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;entityNameLowerCase&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;includeCreate&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;includeRead&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;includeUpdate&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;includeDelete&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt; &lt;span class=&quot;z-entity z-other z-attribute-name z-localname z-xml&quot;&gt;key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator z-key-value z-xml&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;includeEvent&lt;span class=&quot;z-punctuation z-definition z-string z-end z-xml&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;        &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;defaultValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;    &lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-text z-xml&quot;&gt;&lt;span class=&quot;z-meta z-tag z-xml&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-xml&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-localname z-xml&quot;&gt;requiredProperties&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-xml&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;d keep this file open, as you&#x27;ll likely be dipping into and out of it whilst configuring and testing your parameters.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst you have nothing else open though, now might be a good time to ensure any unnecessary directories and&#x2F;or files are removed from the &lt;code&gt;&amp;lt;fileSets&amp;gt;&amp;lt;&#x2F;fileSets&amp;gt;&lt;&#x2F;code&gt; section as everything listed here will be part of every application generated from your archetype.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we know where to edit properties and file sets, we can navigate through our code, found in &lt;code&gt;src&#x2F;main&#x2F;resources&#x2F;archetype-resources&lt;&#x2F;code&gt; and start replacing some stuff with property placeholders.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;using-parameters&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-parameters&quot; aria-label=&quot;Anchor link for: using-parameters&quot;&gt;Using Parameters&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;An example of an out-the-box property is the &lt;code&gt;package&lt;&#x2F;code&gt; property, you will see that Maven has been nice enough to replace all of your package statements with something that looks like this: &lt;code&gt;package ${package};&lt;&#x2F;code&gt;, or &lt;code&gt;package ${package}.repository;&lt;&#x2F;code&gt; etc., depending upon which Java file you open.&lt;&#x2F;p&gt;
&lt;p&gt;Every time you try to generate a project from an archetype, you will be asked by Maven for the base package name. Maven will replace every instance of &lt;code&gt;${package}&lt;&#x2F;code&gt; across your codebase with your input value.&lt;&#x2F;p&gt;
&lt;p&gt;The user of our archetype will also be asked for values to assign to the required properties we recently defined too. We can use the same (&lt;code&gt;${value}&lt;&#x2F;code&gt;) syntax to indicate where these values should be used across our codebase:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;Mono&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-java&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;ServerResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-java&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; getAll$&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;ServerRequest&lt;&#x2F;span&gt; request&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-support z-class z-java&quot;&gt;Flux&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-java&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-comparison z-java&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; $&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityNameLowerCase&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;s &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; repository&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;findAll&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-keyword z-control z-flow z-return z-java&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;ServerResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;            &lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;contentType&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;APPLICATION_JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;            &lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityNameLowerCase&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;s&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; $&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-java&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-stray-parens-end&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You may have noticed that in the earlier &lt;code&gt;requiredProperties&lt;&#x2F;code&gt; example, we defined a few properties that had a default value of &lt;code&gt;true&lt;&#x2F;code&gt;, hinting that they might be used in a boolean expression - good catch:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;java&quot; class=&quot;language-java z-code&quot;&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;z-source z-java&quot;&gt;#&lt;span class=&quot;z-keyword z-control z-conditional z-if z-java&quot;&gt;if&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-parens z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;includeRead&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-comparison z-java&quot;&gt;==&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-java&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-punctuation z-definition z-string z-end z-java&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;)
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;    &lt;span class=&quot;z-storage z-modifier z-java&quot;&gt;public&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;Mono&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-java&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;ServerResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-end z-java&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; getAll$&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-class z-java&quot;&gt;ServerRequest&lt;&#x2F;span&gt; request&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        &lt;span class=&quot;z-support z-class z-java&quot;&gt;Flux&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-generic z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-generic z-begin z-java&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-comparison z-java&quot;&gt;&amp;gt;&lt;&#x2F;span&gt; $&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityNameLowerCase&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;s &lt;span class=&quot;z-meta z-assignment z-rhs z-java&quot;&gt;&lt;span class=&quot;z-keyword z-operator z-assignment z-java&quot;&gt;=&lt;&#x2F;span&gt; repository&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;findAll&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;        &lt;span class=&quot;z-keyword z-control z-flow z-return z-java&quot;&gt;return&lt;&#x2F;span&gt; &lt;span class=&quot;z-support z-class z-java&quot;&gt;ServerResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;                &lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;contentType&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-java&quot;&gt;APPLICATION_JSON&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-end z-java&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;                &lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-java&quot;&gt;&lt;span class=&quot;z-variable z-function z-java&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-section z-parens z-begin z-java&quot;&gt;(&lt;&#x2F;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityNameLowerCase&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;s&lt;span class=&quot;z-punctuation z-separator z-comma z-java&quot;&gt;,&lt;&#x2F;span&gt; $&lt;span class=&quot;z-meta z-block z-java&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-java&quot;&gt;{&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language z-java&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal z-stray-parens-end&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-terminator z-java&quot;&gt;;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;&lt;span class=&quot;z-meta z-block z-java&quot;&gt;    &lt;span class=&quot;z-punctuation z-section z-block z-end z-java&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-java&quot;&gt;#end
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This says that if the &lt;code&gt;includeRead&lt;&#x2F;code&gt; property is set to &lt;code&gt;true&lt;&#x2F;code&gt;, include this section of code. Otherwise, don&#x27;t include this code block.&lt;&#x2F;p&gt;
&lt;p&gt;You can use Maven properties in file names &lt;code&gt;__likeThis__&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;iambenzo.com&#x2F;posts&#x2F;maven-archetypes&#x2F;img&#x2F;file-properties.png&quot; alt=&quot;PropertyFileName&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;post-generation-script&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#post-generation-script&quot; aria-label=&quot;Anchor link for: post-generation-script&quot;&gt;Post-Generation Script&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Finally, you can also provide Maven a groovy script (&lt;code&gt;src&#x2F;main&#x2F;resources&#x2F;META-INF&#x2F;archetype-post-generate.groovy&lt;&#x2F;code&gt; - it has to have this filename and be in this exact location) to run any custom commands &lt;em&gt;after&lt;&#x2F;em&gt; a project has been created from your archetype.&lt;&#x2F;p&gt;
&lt;p&gt;The benefit of this groovy script is that  it has access to all of the properties used to generate a project, so you can do some file clean-up or some extra work based upon certain property values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;groovy&quot; class=&quot;language-groovy z-code&quot;&gt;&lt;code class=&quot;language-groovy&quot; data-lang=&quot;groovy&quot;&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-import z-groovy&quot;&gt;&lt;span class=&quot;z-keyword z-other z-import z-groovy&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-import z-groovy&quot;&gt;java.nio.file.Files
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-import z-groovy&quot;&gt;&lt;span class=&quot;z-keyword z-other z-import z-groovy&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-import z-groovy&quot;&gt;java.nio.file.Path
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-import z-groovy&quot;&gt;&lt;span class=&quot;z-keyword z-other z-import z-groovy&quot;&gt;import&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-import z-groovy&quot;&gt;java.nio.file.Paths
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;Path&lt;&#x2F;span&gt; projectPath &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;Paths&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method-call z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-method z-groovy&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-begin z-groovy&quot;&gt;(&lt;&#x2F;span&gt;request&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;outputDirectory&lt;span class=&quot;z-punctuation z-definition z-separator z-parameter z-groovy&quot;&gt;,&lt;&#x2F;span&gt; request&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;artifactId&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-end z-groovy&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;String&lt;&#x2F;span&gt; includeEvent &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; properties&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method-call z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-method z-groovy&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-begin z-groovy&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;includeEvent&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-end z-groovy&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;String&lt;&#x2F;span&gt; entityName &lt;span class=&quot;z-keyword z-operator z-assignment z-groovy&quot;&gt;=&lt;&#x2F;span&gt; properties&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method-call z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-method z-groovy&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-begin z-groovy&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;entityName&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-end z-groovy&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;
&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-keyword z-control z-groovy&quot;&gt;if&lt;&#x2F;span&gt; (includeEvent &lt;span class=&quot;z-keyword z-operator z-comparison z-groovy&quot;&gt;!=&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;true&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;) &lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-begin z-groovy&quot;&gt;{&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;  &lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;Files&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;deleteIfExists projectPath&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method-call z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-method z-groovy&quot;&gt;resolve&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-begin z-groovy&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;src&#x2F;main&#x2F;java&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-groovy&quot;&gt;+&lt;&#x2F;span&gt; packagePath &lt;span class=&quot;z-keyword z-operator z-arithmetic z-groovy&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&#x2F;model&#x2F;&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-keyword z-operator z-arithmetic z-groovy&quot;&gt;+&lt;&#x2F;span&gt; entityName &lt;span class=&quot;z-keyword z-operator z-arithmetic z-groovy&quot;&gt;+&lt;&#x2F;span&gt; &lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;Event.java&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-end z-groovy&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;  &lt;span class=&quot;z-storage z-type z-class z-groovy&quot;&gt;Files&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;deleteIfExists projectPath&lt;span class=&quot;z-punctuation z-accessor z-dot z-groovy&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-method-call z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-method z-groovy&quot;&gt;resolve&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-begin z-groovy&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-quoted z-double z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;src&#x2F;main&#x2F;java&#x2F;resources&#x2F;public&#x2F;index.html&lt;span class=&quot;z-punctuation z-definition z-string z-end z-groovy&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-method-parameters z-end z-groovy&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-groovy&quot;&gt;&lt;span class=&quot;z-meta z-block z-groovy&quot;&gt;&lt;span class=&quot;z-punctuation z-section z-block z-end z-groovy&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;local-installation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#local-installation&quot; aria-label=&quot;Anchor link for: local-installation&quot;&gt;Local Installation&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now that you&#x27;ve developed your archetype, I&#x27;m sure that you&#x27;ll want to actually use it. From the root directory of your archetype project, run:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mvn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; clean install&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can start using it now!&lt;&#x2F;p&gt;
&lt;p&gt;To use your archetype we navigate to where we&#x27;d like to generate a new project and then enter the following into a terminal:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mvn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; archetype:generate &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DarchetypeGroupId=com.iambenzo&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DarchetypeArtifactId=webflux-crud-archetype&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where the values for the parameters match those defined in your archetype&#x27;s &lt;code&gt;pom.xml&lt;&#x2F;code&gt; - This will allow you to generate a new project in &quot;Interactive Mode&quot;, meaning that you&#x27;ll be asked for values for each required property one-by-one.&lt;&#x2F;p&gt;
&lt;p&gt;You can use the same syntax &lt;code&gt;&quot;-DentityName=Dave&quot;&lt;&#x2F;code&gt; to define your properties ahead of this step. For example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; class=&quot;language-sh z-code&quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-shell&quot;&gt;&lt;span class=&quot;z-variable z-function z-shell&quot;&gt;mvn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt; archetype:generate &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DarchetypeGroupId=com.iambenzo&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DarchetypeArtifactId=webflux-crud-archetype&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DgroupId=com.dave&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DartifactId=dave-api-example&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-Dversion=1.0.0&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DentityName=Dave&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DentityNameLowerCase=dave&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DincludeCreate=true&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DincludeRead=true&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DincludeUpdate=true&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DincludeDelete=true&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt; &lt;span class=&quot;z-punctuation z-separator z-continuation z-line z-shell&quot;&gt;\
&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-source z-shell z-bash&quot;&gt;&lt;span class=&quot;z-meta z-function-call z-arguments z-shell&quot;&gt;&lt;span class=&quot;z-string z-quoted z-double z-shell&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string z-begin z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;-DincludeEvent=true&lt;span class=&quot;z-punctuation z-definition z-string z-end z-shell&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Maven will give you the opportunity to change your mind on any or the properties before generating your new project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;voila&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#voila&quot; aria-label=&quot;Anchor link for: voila&quot;&gt;Voila!&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There you have it. Hopefully you can see the power and potential use-cases for Maven archetypes.&lt;&#x2F;p&gt;
&lt;p&gt;If this blog post is a little difficult to follow, do let me know. You can also &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iambenzo&#x2F;maven-archetype-example&quot;&gt;check out the archetype I created&lt;&#x2F;a&gt; alongside writing this post for extra context.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Flyway</title>
          <pubDate>Tue, 04 Feb 2020 00:00:00 +0000</pubDate>
          <author>Ben Burbage</author>
          <link>https://iambenzo.com/posts/flyway/</link>
          <guid>https://iambenzo.com/posts/flyway/</guid>
          <description xml:base="https://iambenzo.com/posts/flyway/">&lt;p&gt;Anyone who knows me well, knows that I like to make things easier for myself where I can. I&#x27;d like to briefly show you a tool that helps me do that when creating DB interacting web services in Java...Flyway.&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
