Help! My Node.js Docker Image Has Python 🐍 — Uncovering the Right Base Image for Your Node.js App


Hey there,

I’ve just finished putting together everything I know about Node.js container images and figured you might find the write-up useful.

If you’re working with Node.js in Docker, chances are you’ve been hit by the dilemma of which base image to use. Do you go for the default node:latest, the slimmer node:22-slim, or something super minimal like a distroless image? What about Bitnami’s alternative — how does it stack up?

Before you jump headfirst into your next build, you might want to check out my latest iximiuz Labs post, where I dive into some unexpected quirks (like finding a full Python installation in certain Node.js images 😱), the trade-offs between different image types, and best practices for keeping your containers secure and efficient.

Here’s a little taste of what you’ll find inside:

Why Not All Node.js Images Are Created Equal

Did you know that Docker's "official" node:<version> (e.g., node:22), node:lts, and node:latest images include far more than just Node.js? This "fat" image variant has Python, GCC, and hundreds of other packages. That’s why it can balloon up to over 1GB! But if your app doesn’t need to compile native Node.js modules during the npm install step, all that extra bulk is just wasted space and unjustified security risk.

If you’re looking for something more streamlined, the node:<version>-slim image trims a lot of the fat while keeping things fully functional. It’s perfect for most cases where you don’t need to compile your Node.js modules from C++ (read, in 99% of the time).

But Wait… Distroless Images?

For those of you chasing after the smallest, most secure image possible, distroless might sound like the best option. These images come with just the essentials — no shell, no OS package manager, just Node.js and its minimal dependencies. The gcr.io/distroless/nodejs image weighs in at under 150MB and has almost zero CVEs. But the trade-off? The build process gets more complicated, and you also lose debugging flexibility. Want to exec into your container and poke around? Sorry, no shell here. It’s a perfect fit for production, but you need to plan for it.

Bitnami: A Worthy Contender?

Did you know that Bitnami offers a repackaged Node.js container image that, functionality-wise, is very close to Docker's "official" node:<version> but slightly smaller? It comes with many of the same development tools (like Python and GCC), and it’s worth a look if you’re already in the Bitnami ecosystem. However, just like the Docker "official" images, it’s best left for development and build stages and only if you're compiling that C++ code... Otherwise, you'd better steer clear of the unnecessary bloat.

Practical Tips for Node.js Docker Images:

Here are some quick takeaways to keep your Docker images lean, mean, and secure:

For Development/Build: Use node:<version> or bitnami/node:<version> only if you’re compiling native Node.js modules from C++. Otherwise, the node:<version>-slim image is your best bet.

For Production: If you’re running in production, start with node:<version>-slim to reduce most of the bloat with the least amount of effort. But if security and/or size efficiency is a top priority, consider distroless images like gcr.io/distroless/nodejs or Chainguard’s hardened node image, especially if you’re fine with their operational trade-offs (and, in Chainguard's case, pricing).

Avoid the Pitfalls: Never run production applications in the "fat" node:<version> image, and steer clear of node:latest unless you’re just playing around or running demos. And if you’re unfamiliar with Alpine Linux’s quirks (hello musl vs. glibc), approach node:<version>-alpine with caution.

Curious about all the details? Check out the iximiuz Labs post and get the full scoop, including practical examples, security scan results, and tips for using multi-stage builds to keep your containers lightweight.

👉 A Deeper Look into Node.js Docker Images: Help, My Node Image Has Python!

Stay lean, stay secure, and happy building!

Cheers,

Ivan

P.S. My traditional reminder - if you want to learn the Server Side craft faster and support my work, consider getting iximiuz Labs Premium. There is a very good chance you will be able to expense it using your learning and development budget.

Ivan Velichko

Building labs.iximiuz.com - a place to help you learn Containers and Kubernetes the fun way 🚀

Read more from Ivan Velichko

Hello 👋 It's this time of the month again! My traditional roundup of all things Linux, Containers, Kubernetes, and Server Side, delivered straight into your inbox 📬 What I was working on October was very productive for me - I shipped no major iximiuz Labs features (it's always hard to resist the temptation!) and instead dedicated all my available time to content work. The main focus was on Container Images. It's the subject of the first module of my "panoramic" Docker course, and it is almost...

Hello 👋 Ivan's here with a slightly delayed September roundup of all things Linux, Containers, Kubernetes, and Server Side 🧙 What I was working on This month, I worked on an assorted set of topics. Skill Paths First off, the skill paths! I finally finished the underlying machinery, and now iximiuz Labs supports a new type of content - short roadmaps that you can use to develop or improve a specific skill: how to debug distroless containers, how to copy images from one repository to another,...

Hello friends! Ivan's here with another monthly roundup of all things Linux, Containers, Kubernetes, and Server Side 🧙 The issue's main topic is iximiuz Labs' largest-ever upgrade: Fresher and more streamlined look of the frontend UI 💙 A new 5.10 Linux kernel built with nftables support (finally, we can try out kube-proxy's nftables mode). New default playground user - laborant (yep, rootless containers learning for). New playgrounds: Ubuntu 24.04, Debian Trixie, Fedora, and Incus (yay! more...