How Cloud Native Buildpacks Let Us Stop Writing Dockerfiles and Slash Build Config by 90%

You are maintaining seventeen microservices. Every single one has its own Dockerfile. Half of them were written by engineers who left the company. One of them has an apt-get update with no pinned version, and nobody absolutely nobody is brave enough to touch it. That was us. And it was embarrassing.

Sanjai I • May 8, 2026

The Incident That Changed Everything

We had a critical CVE land on our base image on a Friday evening. Node 14, end of life, sitting in production because the engineer who wrote that Dockerfile had moved on and nobody wanted to own the upgrade risk.

Three days. That is how long it took us to patch seventeen services. Three days of pulling engineers off actual product work, of playing archaeology in Docker history, of realizing that our entire containerization strategy was held together by copy-paste and hope.

When we finally finished, our platform lead dropped one sentence in the team channel: "We are never doing this again." Two weeks later, we had Cloud Native Buildpacks running in CI and we have not written a Dockerfile since.

The Dockerfile Is Not Configuration — It Is Hidden Debt

Here is the thing the industry does not want to say out loud: a Dockerfile is just technical debt with a build step attached.

We pretend it is infrastructure. We put it in version control, we review it in pull requests, we feel productive when we optimize layer caching.

But what we are actually doing is making a new engineering decision every single time a new service gets created — and those decisions compound into chaos over two or three years.

Every team writes their Dockerfile their own way. One team uses Alpine, another uses Debian Slim, another uses whatever the junior engineer googled first. Nobody is wrong. That is the actual problem.

There is no standard, and without a standard, you cannot have consistency, and without consistency, you cannot have safety at scale.

What Cloud Native Buildpacks Actually Do

Cloud Native Buildpacks (CNB) is a CNCF specification that converts your source code into a container image without a Dockerfile.

It was born at Heroku and Pivotal — two organizations that had to solve exactly this consistency problem at massive scale before the rest of us even knew it was a problem.

The command-line tool is called pack, and this is the full build command for a Node application:

# one command, no Dockerfile, no decisions
pack build my-app --builder paketobuildpacks/builder:base

It inspects your repository, detects the runtime automatically, pulls the right dependency layers, and produces an OCI-compliant image. No base image debate. No multi-stage gymnastics. No EXPOSE port you forgot to update three sprints ago.

What The Pipeline Looks Like Before And After

CopyBEFORE — The Manual Way
------------------------
Source Code
    |
    v
[ Dockerfile ] <-- handwritten, per service, per team opinion
    |
    v
[ docker build ] <-- inconsistent flags, zero SBOM, manual patches
    |
    v
Container RegistryAFTER - Cloud Native Buildpacks
---------------------------------
Source Code
    |
    v
[ pack build ] <-- one command, zero Dockerfile
    |
    v
[ Detect ] --> [ Compile ] --> [ Export ]
     |               |              |
 finds runtime   installs deps  writes layers
     |               |              |
     +---------------+--------------+
                     |
                     v
          Container Registry
          (SBOM included, rebase-ready)

The builder handles everything. Your team makes zero containerization decisions. That is the point.

The Number That Made Our Jaw Drop

After migrating all seventeen services, we sat down and measured the actual difference.

CopyAverage Dockerfile before   : ~60 lines
Average project.toml after  : ~6 lines

Lines removed per service   : ~54
Services migrated           : 17
Total configuration deleted : ~918 lines

The project.toml that replaced each Dockerfile looks like this:

Copy[_]
schema-version = "0.2"

[[build.buildpacks]]
id = "paketo-buildpacks/nodejs"

918 lines of fragile, handwritten, inconsistently maintained build configuration — gone. That is the 90%.

The Feature Nobody Tells You About: Rebase

This is the capability that would have saved us those three painful days. When a base image CVE lands, you do not rebuild. You rebase.

Copy# swap only the OS layer, leave app layers untouched
pack rebase my-app --run-image new-base-image:patched

The application layer stays completely intact. Only the operating system layer swaps. What used to be three days of cross-team coordination became a twenty-minute operation run once, applied everywhere.

That is not a productivity improvement. That is a different category of engineering entirely.

When CNB Will Fight You

Be honest about this before you migrate. Cloud Native Buildpacks is excellent for standard runtimes — Node, Python, Go, Java, Ruby.

It is not the right tool if your build requires custom binary compilation, obscure system-level dependencies, or environments that no standard buildpack covers.

Also, the builder image is large. First runs on a cold CI environment will feel slow until you configure layer caching properly. Warm the cache once and the problem disappears, but skip that step and you will wonder why you bothered.

Who You Become On The Other Side

Six months after we migrated, something changed that nobody predicted. Engineers stopped being afraid of the build pipeline. New services got containerized correctly on day one without anyone from the platform team holding their hand.

CVE patches went from multi-day incidents to background tasks.

The seventeen Dockerfiles that used to represent seventeen different engineering opinions became one shared standard that nobody had to argue about, document, or defend.