Wednesday, February 19, 2025

Introducing Minimal Application Runtimes in Tanzu Application Catalog and Bitnami Premium

Recently, we announced the general availability of Bitnami Premium, a new commercial upgrade to Bitnami, as well as a new partnership with Arrow Electronics who facilitate a streamlined purchasing process and support experience. Today we are happy to announce an expansion of our commercial offerings with a new set of optimized, performant, minimal, and highly secure application runtimes for the most popular programming languages.

This set of new minimal container images is available now and ready to use in the two commercial versions of Bitnami: Bitnami Premium built on Debian 12, and Tanzu Application Catalog (TAC) built on Photon OS. In this article, we will be using the latter as an example.

Why now and why these minimal container images are a good idea for your applications

Traditionally, Bitnami and hence TAC have focused on delivering high quality, more secure, and consistent Open Source Software applications. Developers and platform engineers know and value that the Bitnami packages are more secure, have tons of knobs and dials, and are very consistent even across multiple operating systems and formats.
Bitnami has always packaged programming language Software Development Kits (SDKs). Whether it was Java, Node.js, or .NET, developers knew our SDKs can be very solid and complete. For example, if your team needed to compile a Python package as part of your Node.js application, you were covered. This completeness comes from many years of serving the development community and their needs. But of course, with time these images grew in size, in contrast with the rest of the applications of the catalog that focus on products running in production and have been optimized over the years.
It is important to note that this situation is not unique to Bitnami. Ivan Velichko explains it better than me in his fantastic essay: Help, my Node image has Python. Official images have become the greatest common denominator for developer needs. That’s ok for development: these are good images for building your apps. But they can be really wrong for running your apps in production.
With the growing interest in our Bitnami Premium initiative, we had more and more customers asking if we had any optimized runtimes for the popular SDKs. We decided that it was time to start focusing on giving our users better runtime alternatives to crafting their own images or needing to rely on third parties to run their applications and ending up with catalog inconsistency. 

Explaining minimal application runtimes

Bitnami’s minimal application runtimes are optimized container images built on top of the essential packages that a container image needs to run on its host. This idea was coined years ago by Google as distroless, because the container images don’t come with a full-blown Linux distribution like Debian or Red Hat. They also leave out software that is useful for development or debugging but that is not needed for running an application in production. This software can be tools, unneeded OS libraries, package managers, documentation, header files, or even Operating System shells.
Bitnami’s minimal application runtimes ship with the bare minimal files needed to run the application on each SDK. The result is container images that:
  • Are reduced in size: By removing unnecessary overhead, the container image contains only the application and its essential dependencies.
  • Expose a smaller threat surface: The exclusion of non-essential files reduces potential security vulnerabilities and reduces the number of CVEs flagged by your scanner—today and tomorrow.
  • Are simpler to maintain: With fewer components to update and manage, security patching and overall maintenance can be more efficient.
  • Are more efficient: With reduced footprint, these images may lower your cloud bill while decreasing application startup time.

The structure of Tanzu Application Catalog minimal application runtimes

To build these minimal application runtimes we decided to start with a trimmed down Photon OS base image for TAC. In Bitnami Premium instead we start from a trimmed down version of Debian Bookworm. Note that in this article, we will focus on TAC. Photon OS is VMware’s enterprise grade security-hardened operating system that, being Open Source and built for cloud and edge applications, gives us a good starting point. From that base image, we remove everything unnecessary and create two base images: static and libgcc. If you have followed the container image ecosystem, this probably sounds very familiar to you. It just follows the same conventions set by Google’s popular distroless images

Once you dive into these images, you’ll find that the static minimal container is a scant 7 MB in size! That’s because it ships just the essentials needed: certificates, timezone data, network files and a basic structure for non-root configuration. On top of that, the libgcc variant adds C, C++ and the GCC runtime library, along with Photon’s FIPS-certified OpenSSL provider. You can check the full inventory from TAC minimal containers in our documentation. If we dig into this image on the TAC software knowledge graph, we’ll easily spot the few packages that this image ships with. 

Both images, static and libgcc are great for running your applications when there are no other SDKs needed. For example, this is a good option for C, C++, Rust and Golang languages or .NET Ahead-of-Time (AOT) bundles, amongst others. 

However, some other programming languages come with their own SDKs. This is the case of languages like Python, Java, .NET and others. Again, in a similar way to the official distroless images, we decided to build the higher-level SDKs on top of the libgcc image as the image below shows.

Using these minimal application runtimes

Ok, so we’ve learned why these minimal runtimes are a great deal and how they are structured. How do we use them though? Well, the idea is very simple: the container image used to develop the application should be a superset of the container image used at runtime. 

How this gets implemented largely depends on your platform. Whether you are using Tanzu Platform, ArgoCD, or GitHub Actions, the answer will be slightly different. To keep things very simple I will provide a sample that just uses Docker. In this case, what we would have to do is to set up a multi-stage build. For this, I’ve taken one of Bret Fisher’s great Node.js and Docker course examples and adapted it a little bit. 

## Stage 1 (production base)
# This gets our prod dependencies installed and out of the way
FROM bitnami/node:22 as base
EXPOSE 3000
ENV NODE_ENV=production
WORKDIR /opt
COPY package*.json ./

# we use npm ci here so only the package-lock.json file is used
RUN npm ci \
&& npm cache clean --force

## Stage 2 (development) # This uses regular Bitnami which is heavy and has all we need FROM base as dev ENV NODE_ENV=development ENV PATH=/opt/node_modules/.bin:$PATH WORKDIR /opt RUN npm install WORKDIR /opt/app CMD ["nodemon", "./bin/www", "--inspect=0.0.0.0:9229"] ## Stage 3 (copy in source for prod) # Finally, copy the built code into the production image which is minimal FROM tac-registry/node-min:22 as prod WORKDIR /opt/app COPY . .
CMD ["node", "./bin/www"]

As you see above, the result ends up being actually quite simple. The base and development images can be based on the regular Bitnami Node.js beefy container image. But for the production environment, we use the minimal application runtime from TAC. 

All that should work seamlessly, but what about the end result? Is the image smaller? Is it “safer”? Well, let’s look at those details next.

Comparing minimal application runtimes to Bitnami development and official images

In this section, we’re going to go through how these images compare to official images for each programming language and also to regular Bitnami development container images. Finally, in the next section, we will dig into one of these ecosystems in detail. 

Let’s start with the overall comparison.

While this data is from January 2025, and sizes will be slightly different once you read this article, at the time of writing we can see a drastic size reduction with TAC application runtimes versus the official images. Nothing less than 94%!! for Python or 92%!! for Ruby. Those are big numbers. But even for Microsoft’s .NET runtime which is actually quite good, we can see a 28% improvement in size.

Let’s focus now on vulnerabilities. We’ve run an OSS scanner,Trivy, against each of these images. If our theory is correct, we should see a considerable difference in the number of CVEs when comparing the official and Bitnami development container images with the new minimal application runtimes. Is that right? Let’s see.

And right it was. The image above is not missing a third column. It just happens that CVEs are 0 in most cases. So there is indeed a fantastic reduction in the CVE surface which these days is more critical for compliance than ever. 

But this test provided another interesting metric to highlight about Bitnami container images. Have you noticed that one CVE in Python? Well, that one was CVE-2024-12254 and it is particularly interesting because you won’t find that one in Python’s official image. Wait, what? 

Yes, that’s correct. This CVE was at that time affecting all container images, both official and not official, shipping Python 3.12 or beyond from upstream. That’s pretty much all containers out there, or at least those that don’t do patch-forking. Scanners do report this CVE on Bitnami containers because our images include a complete SBOM that has details of all the packages that we are installing on top of the operating system. On the other hand, most other images instead will just install Python binaries from a downloaded bundle or perhaps compile them from source, but they won’t include an SBOM reporting the packages they add. Therefore, OSS scanners end up unaware of the container image’s full contents.

Is that extra CVE a good thing then? Well, whereas platform engineers and engineering teams having to upgrade images will certainly be bothered, we believe it is. There is much ground for improvement with vulnerability scanners, but while that happens we think that being honest and complete about what gets installed in containers is very important to our customers – and that vulnerability is pending a fix from the upstream Python community. [Update: the CVE has since been fixed upstream, and all affected apps in free and commercial Bitnami catalogs have been updated with the patch.] That not only provides better compliance with better SBOMs but also could actually save teams from much trouble when that “hidden” CVE happens to be the next log4j.

Digging into one application runtime: Node.js

Finally, in the above comparison, we did go over official images and their Bitnami free alternatives and saw great improvements. However, we also mentioned why those images are focused on development and are likely not a good choice for running applications in production environments. Going through each language ecosystem and doing a deep analysis of all the container images more suitable for running workloads in production would be too lengthy. So, instead, I’m going to go and focus on just one platform, Node.js. I also think the results should extrapolate reasonably well to all the other platforms.

In the next diagram, we’re going to look at the size and CVE footprint of some of the most popular container images used today for Node.js applications. How did I come up with the list? Well for the sake of independence, rather than choosing the container images by myself, I decided to go with the list from Ivan Velichko’s Node.js container analysis post instead. By the way, if you haven’t checked his site, you should. It’s full of great material. 

In that post, Ivan goes into detail about why each of those container images is relevant and also gives an in-depth analysis on both size and CVE footprint. Naturally, Bitnami’s container image does not do well in that comparison. Which makes sense as it is very development focused. But, then, how does the new Node.js minimal runtime perform on that same benchmark? Well, let’s see.

Please, take as much time as needed to go through the infographic above. Looking at the data, TAC’s minimal container images did extraordinarily well. 

We can see a 12% size reduction in our minimal Node.js images versus the smallest image from that benchmark set, which is Chainguard’s. There’s also a staggering ~88% reduction versus the official image and significant reductions compared to all the other slimmed containers too. On the vulnerabilities front, all three Alpine, Chainguard, and TAC versions have zero CVEs reported by Trivy. So, all in all, the results are pretty good. 

Keep an eye out for more updates

We are excited to deliver these new minimal application runtimes to the TAC (Photon) Bitnami Premium (Debian 12) products. They provide a great alternative to application teams to run their applications in production with a lower footprint and minimal threat surface, while also maintaining the consistency and security standards that users from Bitnami are used to. Perhaps the greatest reason to use our minimal images over the alternatives, however, is that you get the Bitnami SDKs for development purposes which also provide great consistency across multiple language runtimes.

If you’d like to learn more about Bitnami Premium, you can visit our partner Arrow’s marketplace page. To read up on Tanzu Application Catalog, visit our webpage. To keep up with the latest on our minimal container images initiative and more, be sure to follow us on X (formerly Twitter) and Linkedin.