The State of Container Build Tools 2026
BuildKit won the build, so the real question in 2026 is cache transport: whether the runner can persist and restore a warm layer cache between jobs decides cost far more than the tool does.
Executive summary
Container image builds sit on the critical path of nearly every deploy, and the tool that performs them sets the ceiling on how fast and how cheap that path can be. In 2026 the tool landscape has settled. BuildKit is the de facto default behind the docker build command, Kaniko holds the daemonless and Kubernetes-native niche, and Cloud Native Buildpacks serve teams that want to skip hand-written Dockerfiles entirely. The era of arguing about which builder to use is largely over; the builder you get by default is good, and most teams use it without thinking about it.
Because the tool question is settled, the cost question has moved somewhere else, and that somewhere is the cache. A container build is, at its core, a sequence of layers, and the single fact that determines whether a build takes eight minutes or three is how many of those layers can be restored from a cache rather than rebuilt from scratch. A cold build that reinstalls every layer dominates the runner bill. A warm layer cache turns the same build into a few changed layers and a fast finish.
The uncomfortable truth for many teams is that the build tool matters less than whether the runner can persist and restore the cache reliably between jobs. BuildKit's inline cache, Kaniko's remote cache, and registry-backed caches all help, but every one of them still pays a transport cost: the cache has to be pulled over the network at the start of each job because the runner that built it is gone. The runners that win are the ones that keep the layer cache local and warm, so the build restores from disk instead of from a registry round-trip.
This report quantifies adoption across the three main tool families and then spends most of its attention on the thing that actually drives build cost: cache behavior. We break down where the minutes go in a cold build, how much each caching strategy recovers, and why base-image churn is a hidden multiplier that punishes teams who rebuild from scratch on every push. The recurring framing, consistent with every Latchkey report, is that most container-build waste is mechanical and addressable without rewriting a single Dockerfile.
The encouraging part is that the highest-return fix is also the least glamorous. Persisting a layer cache across ephemeral CI runners is real platform work that most teams never get around to, which is precisely why it is such a large, untapped saving. A runner layer that ships warm-cache persistence by default captures most of the build-time and cost reduction with no setup, and it compounds with a lower per-minute rate to make image builds dramatically cheaper than a cold, self-managed pipeline.
Modeled share of CI image builds by primary build tool. · Source: Synthesized from public cloud-native survey data (modeled)
Modeled wall-clock for a mid-size service image on a Linux 2-core runner. · Source: Latchkey analysis (modeled)
Email me the report
The full report is right here on this page, free. Want the link in your inbox to read later or share, plus new Latchkey reports as they drop? Drop your email and we will send it over.
Sent! Check your inbox for the report link.
No spam. Unsubscribe anytime.
BuildKit is no longer optional, it is the build
The classic legacy Docker builder has effectively disappeared from CI. BuildKit's parallel layer graph, mount caches, and inline cache export are now the baseline expectation, and most teams get all of it without opting in because it is the default backend behind the docker build command. The years of guidance that began with 'first, enable BuildKit' are obsolete; for the large majority of pipelines, BuildKit is already on.
What BuildKit changed is the shape of the build. The parallel layer graph means independent stages build concurrently instead of in sequence, mount caches let a package manager keep its download cache across builds, and inline cache export embeds cache metadata in the pushed image so a later build can reuse it. These are genuine improvements, and they are the reason a modern Dockerfile builds faster than the same Dockerfile did five years ago.
The practical consequence is that build performance conversations are now about cache transport, not about whether to enable BuildKit. The builder is not the variable anymore; everyone has the good builder. The variable is where the cache lives and how fast the runner can get to it, which is exactly where the next two findings concentrate. The tool question is answered; the cache question is open, and it is the one that decides the bill.
Cache transport, not the build tool, decides cold-build cost
A warm layer cache cuts a typical mid-size build by roughly two thirds, but only if the runner can restore that cache quickly at the start of the job. This is the central finding of the report and the one most teams underweight: the saving is not in the build tool, it is in cache locality. The fastest builder in the world still rebuilds from scratch if the cache it needs is sitting on a machine that no longer exists.
Registry-backed and inline caches help, and they are far better than nothing, yet they all pay a pull cost. At the start of every job the cache has to be fetched over the network, decompressed, and imported before the build can begin restoring layers from it. On a cold ephemeral runner that transport time is pure overhead, and for a cache of any real size it can eat a meaningful fraction of the time the warm cache was supposed to save.
A runner that persists the layer cache locally between jobs removes most of that pull and is where the largest, most consistent savings show up. When the cache is already on local disk, the build skips the fetch entirely and restores unchanged layers at disk speed. The modeled split of where a cold build's minutes go, shown below, makes the target obvious: the base-image, system-package, and dependency layers that dominate a cold build are exactly the layers a warm local cache restores for free.
- A warm layer cache cuts a typical mid-size build by roughly two thirds, but only when the runner can restore it fast.
- Registry and inline caches still pay a per-job pull-and-import cost that a local persistent cache avoids.
- The base-image and dependency layers that dominate a cold build are precisely the ones a warm local cache restores for free.
- Cache locality, not the choice of build tool, is the variable that decides cold-build cost.
Modeled split of billed minutes for a cold container build. · Source: Latchkey analysis (modeled)
Kaniko and Buildpacks win on constraints, not raw speed
Kaniko exists primarily to build container images without a privileged daemon, which is what makes it attractive inside Kubernetes where running a Docker daemon per build is awkward and a security concern. It is chosen for that constraint, not because it wins a head-to-head speed contest. A team that picks Kaniko is usually optimizing for daemonless, rootless builds in a cluster, and accepting whatever build-time tradeoff comes with that.
Buildpacks occupy the other end of the spectrum: they exist to remove the Dockerfile burden for application teams entirely. Instead of hand-writing and maintaining a Dockerfile, a team points Buildpacks at their source and gets a sensibly-constructed image with a managed base and automatic layer reuse. The win is developer ergonomics and standardization across many services, not peak build speed for any one of them.
Neither tool is chosen for being the fastest, and both benefit from the same runner-side cache persistence that helps BuildKit. Kaniko's remote cache and Buildpacks' layer reuse are still cache transports, and they still pay the same pull cost on a cold runner that a warm local cache would eliminate. The tool you pick reflects your security posture and your ergonomics preferences; the cache locality you get reflects your runner, and it is the runner that moves the cost.
Base image churn is a hidden multiplier
The base image and system-package layers are the single largest slice of an uncached build, and they change far less often than application code. A typical service might touch its application layers on every commit but its base image only when someone deliberately bumps it, which might be monthly. Yet a cold build pays for the full base image on every push as if it changed every time, because the cache that would have restored it was thrown away with the previous runner.
This is the hidden multiplier. The most expensive part of the build is also the most stable part, which means it is the part with the highest cache value. Teams that pin their base image and cache these layers aggressively turn most builds into a handful of changed application layers on top of a stable, restored foundation. Teams that rebuild from scratch pay the full base-image cost on every single build, repeatedly purchasing something that did not change.
The fix is partly hygiene and partly infrastructure. On the hygiene side, pinning the base image to a digest and putting the stable system-package installation in its own early layer keeps that layer cacheable. On the infrastructure side, a runner that persists the layer cache locally is what actually delivers the restore, because pinning the layer does nothing if the cache holding it is gone. The two together turn base-image churn from a per-build tax into a once-per-bump cost.
- The base-image and system-package layers are the largest slice of a cold build and the most stable, so they have the highest cache value.
- A cold build repays the full base-image cost on every push even though the base changed only when someone deliberately bumped it.
- Pinning the base to a digest keeps the layer cacheable; a persistent local cache is what actually restores it.
- Together, pinning plus persistence turn base-image churn from a per-build tax into a once-per-bump cost.
Multi-stage builds reward cache locality the most
Multi-stage Dockerfiles, where a heavy builder stage compiles or bundles the application and a slim final stage copies only the artifacts, are now standard practice for producing small, secure images. They are also the build shape that benefits most from a warm local cache, because the expensive builder stage is full of stable layers, toolchains, dependency installs, intermediate compilation, that change far less often than the final application copy.
BuildKit builds the independent stages of a multi-stage Dockerfile in parallel, which is a real speedup, but the larger win is that the builder stage's heavy layers are exactly the ones a warm cache restores. When those layers are local, the build skips straight to the changed application code and the final-stage copy, finishing in a fraction of the cold time. When they are not, the build re-runs the entire builder stage, which is usually the most expensive part of the whole pipeline.
This is why multi-stage builds and cache persistence are complementary rather than alternative optimizations. The multi-stage structure isolates the stable, expensive work into cacheable layers, and the persistent local cache restores those layers instead of recomputing them. A team that adopts multi-stage builds but runs them on cold runners has done half the work and left most of the saving on the table, because the structure is built to be cached and nothing is caching it.
Image build time is invisible until it is on the critical path
For many teams the container build is the slowest single step in the pipeline, and it tends to grow silently. A service that built in two minutes at launch quietly stretches to eight as dependencies accumulate, the Dockerfile gains stages, and a security scan layer is added. Because each addition is small, no single change feels like it slowed the build, and the cumulative drift goes unnoticed until the build is the thing everyone waits on.
The modeled build times, cold versus warm, shown below, make the size of the recoverable gap concrete: the same image that takes well over eight minutes cold lands near three minutes against a warm layer cache. That is not a marginal tuning win, it is the difference between a build that gates every merge for the better part of ten minutes and one that finishes before the engineer has switched context. The minutes are recoverable, and they are recoverable without touching the application.
What makes this so addressable is that the slow path and the fast path run the identical Dockerfile. Nothing about the image changes; only the cache locality does. That is the recurring lesson across container builds: the waste is mechanical, it lives in the runner rather than in the code, and the fix is to put a warm cache where the build can reach it rather than to rewrite the thing being built.
Managed runners make caching the default, not a project
Persisting and restoring a layer cache reliably across ephemeral CI runners is real platform work. It means standing up a cache store, wiring the build to export and import against it, keying the cache so it hits without serving stale layers, and keeping all of that working as the build changes. Most teams know they should do it, scope it as a project, and never quite get to it, which is exactly why warm-cache savings are so consistently left unclaimed.
Managed runners that ship cache persistence out of the box capture most of the warm-cache savings with no setup. The cache lives close to the runner and survives between jobs, so the build restores its stable base-image and dependency layers from local disk instead of rebuilding them or pulling them over the network. The platform work that a team kept deferring is simply already done, and the build is fast on the first run rather than after a quarter of caching effort that never gets prioritized.
That time saving compounds with cost. A warm cache cuts the minutes a build burns, and a managed per-minute rate roughly 70% below GitHub-hosted pricing cuts the price of each remaining minute, so the two effects multiply rather than add. For container-heavy teams, moving the build leg onto managed infrastructure with a persistent cache is among the clearest returns available, because it attacks both the build time and the per-minute rate at the same time with no change to the Dockerfile.
Recommendations
Stop tuning the tool and start persisting the cache
BuildKit is already the default and already good; the build tool is no longer your bottleneck. Redirect the energy you would spend comparing builders toward making the layer cache local and warm between jobs. Cache locality, not the choice of tool, is what moves a cold build from minutes to seconds.
Pin and isolate the base image and system-package layers
The base image and system packages are the largest and most stable slice of a cold build, which makes them the highest-value layers to cache. Pin the base to a digest and put system-package installation in its own early layer so it stays cacheable, then ensure a persistent cache actually restores it. Done together, this turns base-image cost from a per-build tax into a once-per-bump cost.
Structure Dockerfiles to maximize cache hits
Use multi-stage builds to isolate the heavy, stable work into cacheable layers, and order instructions so that frequently-changing application code comes last. Copy manifest files and install dependencies before copying the full source tree, so a code-only change does not invalidate the dependency layer. These are free reorderings that pay back on nearly every build.
Prefer a local warm cache over registry round-trips
Registry-backed and inline caches are better than nothing, but they pay a pull-and-import cost on every cold job. Where you can, run builds on a runner that keeps the layer cache on local disk between jobs, so the build restores from disk instead of fetching the cache over the network. The transport you remove is pure overhead the build was never spending on real work.
Move container-heavy builds onto managed runners with cache persistence
Standing up reliable cache persistence across ephemeral runners is a project most teams defer indefinitely. Managed runners that ship warm-cache persistence by default capture that saving with no setup, and the lower per-minute rate compounds with the reduced minutes, so the build leg gets both faster and cheaper at once.
Outlook
Expect the tool debate to keep fading and the cache debate to keep sharpening. BuildKit's position as the default builder is settled, and the marginal gains from switching tools are small relative to the gains from cache locality, so the teams paying attention will spend 2026 and beyond optimizing where the cache lives rather than which builder produces it. The competitive separation in container builds is increasingly a function of infrastructure, the runner and its cache, rather than of the Dockerfile or the build tool.
Image security and supply-chain requirements will keep pushing builds toward multi-stage Dockerfiles, slim and distroless bases, and added scan layers, all of which lengthen a cold build and therefore raise the value of a warm cache. As the build does more work to be smaller and safer, the penalty for rebuilding that work from scratch every time grows, which makes cache persistence not just a cost optimization but a prerequisite for keeping a hardened build fast.
The durable takeaway is that container-build performance has become a runner problem more than a tooling problem. The build tool you get by default is good enough, and the difference between a fast pipeline and a slow one is whether the runner keeps a warm layer cache the build can reach. The teams that internalize that will treat the persistent cache as basic infrastructure, the way they already treat the builder, and they will spend the next two years building images in a fraction of the time and cost that cold-runner teams keep paying.
Methodology
This report synthesizes publicly available cloud-native and container ecosystem data with Latchkey's own analysis of image-build runner economics. Adoption shares are modeled from public survey direction and typical CI build configurations, not a single primary survey. Build-time figures are modeled for a mid-size service image on a Linux 2-core hosted runner and will vary with image shape, base, and cache strategy. Figures labeled "modeled" are illustrative estimates derived from public pricing and typical pipeline shapes, not a primary survey; figures attributed to a named source reflect that source. Pricing reflects published rates at time of writing and should be verified against current provider pricing.