Buildpacks promise source-to-image generation. No need to write a Dockerfile or maintain dependencies. Get started with golden configurations for languages, frameworks, and more.
Too good to be true?
Buildpacks originated at Heroku, so there's no coincidence they are closely tied to the idea of a PaaS.
But Buildpacks aren't the best abstraction.
- Fragmented configuration. Defining exactly an application package is too difficult a task. Either the configuration is too broad, and you end up with bloated images, or it is too niche to be useful. Knobs are gradually exposed until the API surface is so large that it ceases to be a useful abstraction.
- Gradually, then suddenly. You can defer DevOps work by using a buildpack. It might even work out of the box. But when you encounter the edge of possibilities (often quickly), it requires you to suddenly take on all of the work you skipped – Dockerfiles, CI pipelines, configuration, etc. Dropping to a lower level of abstraction is so common that it creates unnecessary friction.
- Maintenance is harder, not easier. Even in an open-source model, you're dealing with M language runtimes multiplied by N supported versions. Not to mention bespoke configuration options. And that's just language runtimes, not including frameworks or higher-level abstractions. Moreover, buildpacks do not magically solve dependency and security issues. More at PaaS Design Principles.
Buildpacks make sense if you're building your own PaaS, but that is becoming less common (Are Platform Teams Dead?). They often are introduced by a centralized team more for compliance than convenience. However, there are probably ways to accomplish the same with native Dockerfiles and containers.
The trade-off between Dockerfiles and buildpacks is challenging for many developers to assess. We're usually much better at identifying upfront costs rather than future costs. And Dockerfiles have an initial learning curve.