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
Explaining minimal application runtimes
- 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 wayFROM bitnami/node:22 as baseEXPOSE 3000ENV NODE_ENV=productionWORKDIR /optCOPY package*.json ./
# we use npm ci here so only the package-lock.json file is usedRUN 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.