<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>A Desipient Blog - rust</title>
    <link rel="self" type="application/atom+xml" href="https://desipient.com/tags/rust/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://desipient.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-05-14T00:00:00+00:00</updated>
    <id>https://desipient.com/tags/rust/atom.xml</id>
    <entry xml:lang="en">
        <title>Ridiculously Tiny, Auditable Images with Rust and Distroless</title>
        <published>2026-05-14T00:00:00+00:00</published>
        <updated>2026-05-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://desipient.com/blog/ridiculously-tiny-auditable-images/"/>
        <id>https://desipient.com/blog/ridiculously-tiny-auditable-images/</id>
        
        <content type="html" xml:base="https://desipient.com/blog/ridiculously-tiny-auditable-images/">&lt;h2 id=&quot;the-white-rabbit-trivy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-white-rabbit-trivy&quot; aria-label=&quot;Anchor link for: the-white-rabbit-trivy&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
The White Rabbit - Trivy&lt;&#x2F;h2&gt;
&lt;p&gt;I recently had fun building a little &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sumebrius&#x2F;ai-operator&quot;&gt;toy app&lt;&#x2F;a&gt; in rust,
and when the time came to containerising and deploying it, I found myself going down a rabbit hole
of miniaturisation. This is the story of that rabbit hole.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;TLDR:&lt;&#x2F;strong&gt; We’re going to wind up building a tiny image with a minimal surface area for vulnerabilities
and full auditability - jump to the end for the final Containerfile&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;&#x2F;p&gt;
&lt;p&gt;This leporid journey starts with insecurity. That is, on initially building the application into an
image based (arbitrarily) on a debian image and scanning with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;aquasecurity&#x2F;trivy&quot;&gt;Trivy&lt;&#x2F;a&gt;,
I find myself irrationally annoyed by a distressing number of vulnerabilities&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;&#x2F;p&gt;
&lt;p&gt;On further investigation, I’m further irrationally annoyed by the fact that not only are all of the
vulnerabilities from my arbitrary base, but Trivy evidently has no knowledge of my own app’s
dependencies.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phase-1-application-auditability&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#phase-1-application-auditability&quot; aria-label=&quot;Anchor link for: phase-1-application-auditability&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Phase 1 - Application Auditability&lt;&#x2F;h2&gt;
&lt;p&gt;Fortunately, letting Trivy know about what dependencies we use in an application is trivial&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;, courtesy
of some existing tooling - namely the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;cargo-auditable&quot;&gt;cargo auditable plugin&lt;&#x2F;a&gt;.
This works by generating an SBOM (Software Bill Of Materials) and stuffing it right into the compiled binary.&lt;&#x2F;p&gt;
&lt;p&gt;To make use of this, we simply install the plugin and use that for building our binary in the build stage of
our Containerfile:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;docker&quot; data-name=&quot;Containerfile&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo install cargo-auditable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; Cargo.lock Cargo.toml .&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; src&#x2F; src&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo auditable build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;phase-2-getting-rid-of-base-image-vulnerabilities&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#phase-2-getting-rid-of-base-image-vulnerabilities&quot; aria-label=&quot;Anchor link for: phase-2-getting-rid-of-base-image-vulnerabilities&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Phase 2 - Getting rid of base image vulnerabilities&lt;&#x2F;h2&gt;
&lt;p&gt;Again existing tooling comes to the rescue, in the form of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GoogleContainerTools&#x2F;distroless&quot;&gt;“Distroless” Container Images&lt;&#x2F;a&gt;,
designed specifically for the problem of runaway dependencies. Considering our application is a single binary,
we don’t really need much at all from our base and we’re right in the target audience.&lt;&#x2F;p&gt;
&lt;p&gt;Swapping out the base for our final application image from &lt;code&gt;debian:trixy-slim&lt;&#x2F;code&gt; to &lt;code&gt;distroless&#x2F;cc-debian13:nonroot&lt;&#x2F;code&gt;&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;
is fairly straight-forward, and immediately gets our image’s vulnerability count down to zero.&lt;&#x2F;p&gt;
&lt;p&gt;As a nice little side-effect, it also drops our image size from an already respectable 34MiB to an impressive 14.3MiB.&lt;&#x2F;p&gt;
&lt;p&gt;As a side-side-effect, it also gives me an irrational urge to see just how small we can make this thing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phase-3-static-compilation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#phase-3-static-compilation&quot; aria-label=&quot;Anchor link for: phase-3-static-compilation&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Phase 3 - Static Compilation&lt;&#x2F;h2&gt;
&lt;p&gt;What we really, really want is to&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-5-1&quot;&gt;&lt;a href=&quot;#fn-5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; be able to use the distroless &lt;code&gt;static&lt;&#x2F;code&gt; base - but to do this we need to make
sure our binary is truly statically compiled.&lt;&#x2F;p&gt;
&lt;p&gt;Static compilation with rust is easy-ish enough, we just need to set a &lt;del&gt;magic incantation&lt;&#x2F;del&gt; &lt;code&gt;RUSTFLAG&lt;&#x2F;code&gt; to target
the feature &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;linkage.html#r-link.crt.crt-static&quot;&gt;`-C target-feautre=+crt-static&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And immediately we’re struck with a wall of linking errors to symbols in &lt;code&gt;libcrypto-lib-c_zlib.o&lt;&#x2F;code&gt;…&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-side-quest-rustls&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-side-quest-rustls&quot; aria-label=&quot;Anchor link for: the-side-quest-rustls&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
The Side Quest - rustls&lt;&#x2F;h3&gt;
&lt;p&gt;The reqwest library, used extensively by our toy app considering it mostly just wraps around calling an API, has two
available backends for dealing with TLS:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;native-tls&lt;&#x2F;code&gt; - which wraps the OS TLS frameworks (or the ubiquitous OpenSSL library)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;rustls&lt;&#x2F;code&gt; - a rust native library&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;rustls&lt;&#x2F;code&gt;, for hopefully evident reasons, is what we want for our use case. It’s also the default choice with the
default reqwest feature flags. However, watching compilation and digging through our cargo.lock manifest, for some
undocumented&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-6-1&quot;&gt;&lt;a href=&quot;#fn-6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; reason it appears that when combined with the &lt;code&gt;tokio&lt;&#x2F;code&gt; asynchronous runtime (also used extensively by our
toy app) then the &lt;code&gt;native-tls&lt;&#x2F;code&gt; dependency is preferred instead.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, it’s easy enough, if fiddly, to simply be very specific about our feature flags in our cargo dependencies:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;toml&quot; data-name=&quot;cargo.toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;reqwest&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt; version&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;0.12.24&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    &amp;quot;json&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;    # Force rustls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    &amp;quot;rustls-tls&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;    # Defaults except native-tls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    &amp;quot;charset&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    &amp;quot;http2&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;    &amp;quot;system-proxy&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; default-features&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;where-were-we&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-were-we&quot; aria-label=&quot;Anchor link for: where-were-we&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Where were we?&lt;&#x2F;h3&gt;
&lt;p&gt;And back from our sidequest, we’re now compiling again. Swapping to the static distroless base for the final image,
we’re now down to ~4.9MiB. Pow! now we’re in truly tiny image territory!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phase-4-smaller-aka-using-musl&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#phase-4-smaller-aka-using-musl&quot; aria-label=&quot;Anchor link for: phase-4-smaller-aka-using-musl&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Phase 4 - Smaller! (aka using musl)&lt;&#x2F;h2&gt;
&lt;p&gt;We may be tiny already, but by this stage my irrational urge for miniaturisation has become a full-blown obsession.
Next step, let’s try replacing those old, stodgy glibc std lib with musl - the standard library used by the famously
tiny (but not tiny enough) alpine distro based images.&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;markdown-alert-caution&quot;&gt;
&lt;p&gt;If you care about such inane things as “performance” or “reliability” - you probably want to either ignore this
section&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-7-1&quot;&gt;&lt;a href=&quot;#fn-7&quot;&gt;7&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; or do some thorough benchmarking. musl is not a drop in replacement for glibc with regards to
compatibility or performance.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;There’s a few steps to this, but nothing too onerous.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Use a musl friendly alpine base for our build image&lt;&#x2F;li&gt;
&lt;li&gt;Install the &lt;code&gt;musl-dev&lt;&#x2F;code&gt; - this isn’t installed by default in the base as it’s not exactly a common requirement.&lt;&#x2F;li&gt;
&lt;li&gt;Ensure we target the correct platform triplet&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;With these changes, we’re now down to a smidge under 4.5MiB. glibc added 400 whole KiB of bloat to our image.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phase-5-even-smaller-aka-distrolessless&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#phase-5-even-smaller-aka-distrolessless&quot; aria-label=&quot;Anchor link for: phase-5-even-smaller-aka-distrolessless&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Phase 5 - Even Smaller! (aka distrolessless)&lt;&#x2F;h2&gt;
&lt;p&gt;While doing this write-up, a now obvious-in-hindsight thought came to me… Our binary is now fully self-contained, is
there anything we even need from our static distroless base? Long answer, all it really provides are tzinfo (not needed,
as long as we’re happy to keep everything in UTC) and ca-certificates (not used, as we’ve baked our trust store directly
into the binary with rustls).&lt;&#x2F;p&gt;
&lt;p&gt;Short answer, no.&lt;&#x2F;p&gt;
&lt;p&gt;Replacing our base for the final image with &lt;code&gt;FROM scratch&lt;&#x2F;code&gt; to build it from a literal bare base, we now get a (yes,
working) image with a total size of: &lt;strong&gt;3.61MiB&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;docker&quot; data-name=&quot;Containerfile&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# Image build base&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; rust:1-alpine &lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; builder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# Our musl build dependency&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; apk add --no-cache musl-dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# For our SBOM generation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo install cargo-auditable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# Tell rustc to statically link everything&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;ENV&lt;&#x2F;span&gt;&lt;span&gt; RUSTFLAGS=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;-C target-feature=+crt-static&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; Cargo.lock Cargo.toml .&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; src&#x2F; src&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo auditable build --release --target x86_64-unknown-linux-musl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# Runtime image &amp;quot;base&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; scratch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# The binary is literally the only thing we need&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder &#x2F;build&#x2F;target&#x2F;x86_64-unknown-linux-musl&#x2F;release&#x2F;ai-operator &#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# Oh and a bit of metadata about how to actually run...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;EXPOSE&lt;&#x2F;span&gt;&lt;span&gt; 3000&#x2F;tcp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;CMD&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;quot;&#x2F;bin&#x2F;ai-operator&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;phase-6-still-smaller-aka-compiler-optimisation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#phase-6-still-smaller-aka-compiler-optimisation&quot; aria-label=&quot;Anchor link for: phase-6-still-smaller-aka-compiler-optimisation&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Phase 6 - Still Smaller! (aka compiler optimisation)&lt;&#x2F;h2&gt;
&lt;p&gt;At this stage, there’s nothing more we can do to reduce this from an image build perspective. The image layers
are literally just the binary itself and metadata - there’s simply nothing left to strip out.&lt;&#x2F;p&gt;
&lt;p&gt;Any further reductions will need to target shrinking the binary itself, but fortunately(?) the rust compiler defaults
don’t optimise for binary size - and we have some levers to pull here.&lt;&#x2F;p&gt;
&lt;p&gt;Updating our release &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;profiles.html#profile-settings&quot;&gt;profile settings&lt;&#x2F;a&gt;
with a fairly naive set of size-oriented optimisations, we’re now down to 2.1MiB:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Stripping all symbols out of the binary - yes these are injected by default in the release profile!&lt;&#x2F;li&gt;
&lt;li&gt;Setting our optimisation level for size, not speed&lt;&#x2F;li&gt;
&lt;li&gt;Enabling link time optimisation, and forcing a single codegen unit to eliminate optimisation boundaries.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;toml&quot; data-name=&quot;cargo.toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;profile.release&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;strip&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;symbols&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;opt-level&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;quot;z&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;codegen-units&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There’s something else we can do here to shave off a surprising number of bytes - eliminating runtime panic unwinds.
By setting &lt;code&gt;panic = &quot;abort&quot;&lt;&#x2F;code&gt; we remove any stdlib stack traces for any possible panics.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-8-1&quot;&gt;&lt;a href=&quot;#fn-8&quot;&gt;8&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This gives us a final score of… &lt;strong&gt;1.89MiB&lt;&#x2F;strong&gt; for the entire image.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-next&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-next&quot; aria-label=&quot;Anchor link for: where-next&quot;&gt;&lt;i class=&quot;icon&quot;&gt;&lt;&#x2F;i&gt;&lt;&#x2F;a&gt;
Where next?&lt;&#x2F;h2&gt;
&lt;p&gt;Aside from nerfing the aforementioned panic handling, we’re starting to run of things to eliminate without taking a
hatchet to the code itself.&lt;&#x2F;p&gt;
&lt;p&gt;If I were to really let the obsession take me well and truly beyond reason, there are some static assets bundled in the
binary that would make obvious targets to explore eliminating:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ignoring Phase 1&lt;&#x2F;strong&gt; and just don’t add our SBOM. Who cares about security, anyway?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Stripping superfluous trust certs&lt;&#x2F;strong&gt; - We’re currently bundling a full trust store with reqwest. Considering we’re
only really hitting a single endpoint, we could get very fiddly and add ourselves some maintenance burden by manually
building our own trust store consisting of the single ca at the root of our target endpoint (and pray the provider
doesn’t change it)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;Or Dockerfile, if you’re one for brand names. &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;Even if none of them are &lt;em&gt;particularly&lt;&#x2F;em&gt; high. &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;One might even say… &lt;em&gt;Trivyal&lt;&#x2F;em&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;Turns out while we don’t need much from our base, we still need &lt;em&gt;something&lt;&#x2F;em&gt;. The distroless base gives us
glibc + libssl, and the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GoogleContainerTools&#x2F;distroless&#x2F;blob&#x2F;main&#x2F;cc&#x2F;README.md&quot;&gt;cc&lt;&#x2F;a&gt; variants
also gives us glibcc1 - all of which turn out to be required by our binary courtesy of dependencies. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-5&quot;&gt;
&lt;p&gt;zig-a-zig-ah &lt;a href=&quot;#fr-5-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-6&quot;&gt;
&lt;p&gt;If anybody has any clue as to why, I would be glad to acquire this knowledge from you… &lt;a href=&quot;#fr-6-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-7&quot;&gt;
&lt;p&gt;Actually you should probably just ignore this entire blog &lt;a href=&quot;#fr-7-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-8&quot;&gt;
&lt;p&gt;This setting hasn’t made it into the final image though, as this is likely an optimisation beyond reason. Stack
traces are too useful when things go pear shaped. &lt;a href=&quot;#fr-8-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
</feed>
