Build Docker images faster and increase DevOps productivity with multi-stage builds

Docker images are an essential component for building containers because they serve as the base of a container. Dockerfiles – lists of instructions that are automatically executed - are written to create specific Docker images. Avoiding large images speeds up the build and deployment of containers, thus contributing positively to your DevOps performance metrics.

Keeping image sizes low can prove challenging. Each instruction in the Dockerfile adds one additional layer to the image, contributing to the size of the image. Shell tricks had to be otherwise employed to write a clean, efficient Dockerfile and to ensure that each layer has the artifacts it needs from the previous layer and nothing else, all of which takes effort and creativity, in addition to being error prone. It was also not uncommon to have separate Dockerfiles for development and a slimmed down version for production, commonly referred to as the "builder pattern". Maintaining multiple Dockerfiles for the same project is not ideal as it could produce different results between development and production, making software development, testing and bug fixes unreliable when pushing new code.

Docker introduced multi-stage builds to solve for the above, which Aptible now supports when using Dockerfile Deploys. Please note that users deploying using the Direct Docker Image Deployment method on Aptible could have used multi-stage builds prior to this release.

Using multi-stage builds

With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.

You can learn more about how to use the FROM instructional statements, naming different build stages in your Dockerfile, picking up from when a previous stage was left off, and more here.