Opens in a new tab
vmblog logo 2024 wht (updated)

Buildpacks vs Dockerfiles: choose an entry point into the cloud

Share: 

David Marshall | Published: October 5, 2023

Containerization technologies evolve continuously to meet the emerging demands of developers and DevOps experts. One such need is automating and facilitating the process of building container images. Enter buildpacks – a solution for building runnable containers out-of-the-box, sidestepping the lengthy Dockerfiles.

Should you switch to buildpacks or continue building containers manually? This article highlights the key aspects of both approaches, helping you to choose an optimal solution for your needs.

Accelerating development with buildpacks

Buildpacks are a set of executables that analyze the application code and turn it into a fully functional OCI-compliant container image. Buildpacks have been around for over a decade; the first ones were introduced in 2011 by Heroku. Heroku cooperated with Pivotal in 2018 to establish a project called Cloud Native Buildpacks. The project became part of the Cloud Native Computing Foundation the same year. In addition, many organizations have integrated the buildpack technology into their ecosystem, for instance, Cloud Foundry, Google, etc. 

The beauty of buildpacks is that they eliminate the need to write Dockerfiles and configure the containers manually. Let’s look under the hood of the technology to understand how it is made possible.

Buildpacks operate in two phases: detect and build.

  • During the detect phase, the application source code is analyzed to determine whether a buildpack is applicable.
  • During the build phase, the buildpack provides the build and run environment for the application, downloads the dependencies, compiles the code if necessary, and specifies the entry point and startup scripts.

The resulting container image is production-ready and can run on any cloud. However, it is not carved in stone and can be customized to meet specific requirements.

Besides ease of use (building an out-of-the-box container image requires only one command), buildpacks possess several capabilities absent from traditional Dockerfiles. For instance, developers can extract a software bill of materials (SBOM) – an indispensable part of a robust supply chain security strategy.

Java developers can use Paketo buildpacks that implement Cloud Native Buildpacks specifications and are recommended for Spring Boot applications. Paketo buildpacks offer a variety of JVMs to choose from: Liberica JDK (default), Oracle JDK, Azul Zulu, Eclipse OpenJ9, etc. It is also possible to adjust the JVM settings: specify the Java version, choose either JDK or JRE, change the web server, and configure other useful parameters (garbage collection, number of threads, and so on). This way, buildpacks do all the heavy lifting in building a container image, which can be further tweaked for enhanced performance.

All in all, buildpacks are a great modern solution as they

  • Integrate smoothly into a CI/CD pipeline,
  • Promote automation in terms of building, updating, and patching container images.

Minimizing resource consumption with lightweight containers

Buildpacks facilitate developers’ lives greatly and speed up the development process, but sometimes, the size of a resulting container is more important, especially for enterprises striving to optimize cloud costs. In this case, developers must write a Dockerfile the old-school way and manually minimize the container image. What are the options?

Distroless containers gained traction in recent years because they are claimed to contain only the application with its dependencies, leaving out the OS layer (although technically, they contain traces of a Linux distro). While it is true that the most miniature distroless images take up only 2.34 MiB, they are fit for statically-linked applications and not suitable for Java because a Java runtime is still required. Below are several more appropriate solutions for cloud-native Java programs:

  • Select a small base OS image. There are numerous open-source Linux distributions for server and cloud deployments – opt for the smallest ones, like Alpine or Alpaquita, with a base image smaller than 5 MiB. This way, you will achieve a significant container size reduction without any additional configurations. Importantly, Alpaquita Linux comes with two libc variants, musl and glibc, which is convenient if you previously used a glibc-distro and don’t want to deal with compatibility issues.
  • Use jlink to build a custom JDK. The jlink tool is available with Java versions 9+. It enables the developers to cut out a custom JDK image containing only the modules required for their application to run.
  • Employ useful Docker commands for compressing container images. To reduce the image size even more, use .dockerignore to list the files that shouldn’t be copied into the final container image. You can also use docker-slim (available with the DockerSlim tool), which analyzes the application, decides which files it needs, and creates a compact container. However, this tool should be used carefully because it may exclude files the application requires due to lazy loading.

Conclusion

Ultimately, the choice of a containerization approach depends on business requirements. Buildpacks are great for IT teams that want to automate and accelerate development. Besides, the resulting container images are not less performant or secure than containers built manually. For dense cloud deployments where every MiB is significant, consider building Java containers manually, considering the above recommendations.

++

Join us at KubeCon + CloudNativeCon North America this November 6 – 9 in Chicago for more on Kubernetes and the cloud native ecosystem. 

##

ABOUT THE AUTHOR

Dmitry Chuyko 

Dmitry Chuyko is a Senior Performance Architect at BellSoft, an OpenJDK committer, and a public speaker. Prior to joining BellSoft, Dmitry worked on the Hotpot JVM at Oracle, and before that he had many years of programming experience in Java. He is currently focused on optimizing HotSpot for x86 and ARM, previously being involved in rolling out JEP 386, which enables the creation of the smallest JDK containers. Dmitry continues his journey in the containerization process and is happy to share his insights and expertise in this field.