What is Dockerfile ONBUILD?

The ONBUILD instruction adds a trigger instruction to an image, which will be executed later, when the image is used as the base for another build. It's useful for creating reusable base images that can be customized. ONBUILD allows for the creation of "build templates" for similar images.

The Dockerfile ONBUILD instruction is a powerful tool in the world of containerization and orchestration. It allows developers to specify commands that will be executed later, during the build of a child image. This instruction is a cornerstone of Docker's flexibility and modularity, enabling the creation of base images that can be customized and extended by other Dockerfiles.

Understanding the ONBUILD instruction, its use cases, and its role in the broader context of containerization and orchestration is crucial for any software engineer working with Docker. This glossary entry will delve into the depths of the ONBUILD instruction, providing a comprehensive exploration of its functionality, history, and practical applications.

Definition of Dockerfile ONBUILD

The ONBUILD instruction in a Dockerfile is a command that adds to the image a trigger instruction to be executed at a later time. This trigger will be activated when the image is used as the base for another build. The ONBUILD instruction effectively allows a Dockerfile to defer certain operations until it is extended by another Dockerfile.

ONBUILD commands are useful when you are building an image which will be used as a base for building other images. They allow you to specify operations that you want to defer until the child image is built, such as installing dependencies or setting environment variables.

ONBUILD Syntax

The ONBUILD instruction follows a specific syntax in a Dockerfile. It is followed by any other valid Dockerfile instruction. The syntax is as follows: ONBUILD [INSTRUCTION]

For example, to set a trigger that will install npm dependencies when the image is used as a base, you would write: ONBUILD RUN npm install. This means that the npm install command will not be executed when the current Dockerfile is built, but will be executed when a child Dockerfile FROM this image is built.

ONBUILD Limitations

While the ONBUILD instruction is powerful, it does come with certain limitations. One of the main limitations is that ONBUILD instructions cannot be chained. That is, an ONBUILD instruction cannot itself include another ONBUILD instruction. This limitation is in place to prevent the possibility of infinite loops in Dockerfile builds.

Another limitation is that the ONBUILD instruction cannot be used with the FROM or MAINTAINER instructions. This is because these instructions do not make sense to defer until a child image is built. The FROM instruction specifies the base image for the current build, and the MAINTAINER instruction is deprecated.

Explanation of Dockerfile ONBUILD

The ONBUILD instruction is a key part of Docker's philosophy of 'build once, run anywhere'. By allowing developers to defer certain operations until a child image is built, it enables the creation of generic base images that can be customized for specific use cases.

When a Dockerfile with an ONBUILD instruction is built, the ONBUILD instructions are not executed immediately. Instead, they are added to the image's metadata. When a child image is built FROM the parent image, the ONBUILD instructions are retrieved from the parent image's metadata and executed before the child Dockerfile's own instructions.

ONBUILD in Action

Let's consider a practical example to better understand the ONBUILD instruction. Suppose you are creating a base image for Node.js applications. You want to defer the installation of npm dependencies until a child image is built, because the specific dependencies will depend on the application.

In your Dockerfile, you would include the instruction: ONBUILD RUN npm install. When this Dockerfile is built, the npm install command is not executed. Instead, it is stored in the image's metadata. When a child Dockerfile FROM this image is built, the npm install command is retrieved from the parent image's metadata and executed before the child Dockerfile's own instructions.

ONBUILD and Layering

The ONBUILD instruction also plays a role in Docker's layering system. Each instruction in a Dockerfile creates a new layer in the Docker image. Layers are stacked on top of each other to form the final image. When an ONBUILD instruction is executed, it creates a new layer in the child image.

This layering system is part of what makes Docker images so lightweight and fast to build. Only the layers that have changed need to be rebuilt, and layers can be shared between images. The ONBUILD instruction allows developers to control when and how layers are created, contributing to the efficiency and flexibility of Docker.

History of Dockerfile ONBUILD

The ONBUILD instruction has been a part of Docker since its early days. Docker was first released in 2013, and the ONBUILD instruction was introduced in version 0.8, released in February 2014. The introduction of the ONBUILD instruction was part of Docker's ongoing efforts to make containerization more flexible and modular.

Since its introduction, the ONBUILD instruction has been widely adopted by the Docker community. It is commonly used in base images for various programming languages and frameworks, such as Node.js, Ruby on Rails, and Django. The ONBUILD instruction has proven to be a powerful tool for creating reusable, customizable Docker images.

Evolution of ONBUILD

While the basic functionality of the ONBUILD instruction has remained the same since its introduction, its usage patterns have evolved over time. In the early days of Docker, it was common to use ONBUILD instructions for a wide range of operations, including installing dependencies, setting environment variables, and even running tests.

However, as the Docker community has grown and matured, best practices for using the ONBUILD instruction have emerged. Today, it is generally recommended to use ONBUILD instructions sparingly, and only for operations that truly need to be deferred until a child image is built. This is because excessive use of ONBUILD instructions can make Dockerfiles harder to read and maintain, and can lead to unexpected behavior if the triggers are forgotten or misunderstood.

ONBUILD in the Docker Ecosystem

The ONBUILD instruction is just one piece of the larger Docker ecosystem. Docker is a platform for developing, shipping, and running applications in containers. It provides a standardized way to package applications with their dependencies into a portable container, which can be run on any system that has Docker installed.

The Docker ecosystem includes a wide range of tools and technologies, including Docker Compose for defining and running multi-container applications, Docker Swarm for native clustering and orchestration, and Docker Hub for sharing and distributing Docker images. The ONBUILD instruction plays a key role in this ecosystem, enabling the creation of flexible, reusable Docker images that can be customized for specific use cases.

Use Cases of Dockerfile ONBUILD

The ONBUILD instruction is particularly useful in scenarios where you want to create a base image that will be extended by other Dockerfiles. This is common in organizations that have a standard base image for a particular language or framework, which individual teams then customize for their specific applications.

Another common use case for the ONBUILD instruction is in open-source projects. Many open-source projects provide a Dockerfile for their project, which users can extend to customize the application for their own needs. The ONBUILD instruction allows these projects to defer certain operations, such as installing dependencies or compiling code, until the user builds their own Dockerfile.

ONBUILD in Node.js Applications

One of the most common use cases for the ONBUILD instruction is in Dockerfiles for Node.js applications. The Node.js community has a strong culture of modular, reusable code, and this extends to Docker as well. Many Node.js Dockerfiles use the ONBUILD instruction to defer the installation of npm dependencies until a child image is built.

This allows the creation of a generic Node.js base image, which can be extended by individual applications with their own package.json files. The ONBUILD RUN npm install instruction ensures that the correct dependencies are installed for each application, without having to duplicate the npm install command in every Dockerfile.

ONBUILD in Multi-Stage Builds

The ONBUILD instruction can also be useful in multi-stage Docker builds. A multi-stage build is a Dockerfile that includes multiple FROM instructions, effectively creating multiple temporary images that are used to build the final image. This can be useful for separating the build-time and runtime environments, or for creating smaller, more efficient images.

In a multi-stage build, the ONBUILD instruction can be used to defer operations until a later stage of the build. For example, you might have a build stage that compiles your application code, and a runtime stage that runs the compiled code. You could use an ONBUILD instruction in the build stage to defer the compilation until the runtime stage, ensuring that the compiled code is fresh and up-to-date.

Examples of Dockerfile ONBUILD

Let's look at some specific examples of how the ONBUILD instruction can be used in a Dockerfile. These examples will illustrate the flexibility and power of the ONBUILD instruction, and demonstrate how it can be used to create modular, reusable Docker images.

It's important to note that these examples are just that - examples. The ONBUILD instruction can be used in many different ways, and the best way to use it will depend on your specific use case and requirements.

Example: Node.js Base Image

Here's an example of a Dockerfile for a Node.js base image that uses the ONBUILD instruction:


# Use the official Node.js 14 image as the base
FROM node:14

# Set the working directory
WORKDIR /usr/src/app

# Copy the package.json and package-lock.json files
ONBUILD COPY package*.json ./

# Install npm dependencies
ONBUILD RUN npm install

# Copy the application code
ONBUILD COPY . .

# Expose port 8080
EXPOSE 8080

# Start the application
CMD [ "node", "server.js" ]

This Dockerfile uses the ONBUILD instruction to defer the copying of the application code and the installation of npm dependencies until a child image is built. This allows the base image to be reused for different Node.js applications, each with their own code and dependencies.

Example: Multi-Stage Build

Here's an example of a Dockerfile for a multi-stage build that uses the ONBUILD instruction:


# Build stage
FROM golang:1.14 AS build
WORKDIR /src
ONBUILD COPY . .
ONBUILD RUN go build -o app

# Runtime stage
FROM debian:buster
WORKDIR /app
COPY --from=build /src/app .
CMD [ "./app" ]

This Dockerfile uses the ONBUILD instruction in the build stage to defer the copying and compilation of the application code until the runtime stage. This ensures that the compiled code is fresh and up-to-date when the final image is built.

Conclusion

The Dockerfile ONBUILD instruction is a powerful tool in the world of containerization and orchestration. By allowing developers to defer certain operations until a child image is built, it enables the creation of flexible, reusable Docker images. Whether you're building a base image for a Node.js application, creating a multi-stage build, or just trying to make your Dockerfiles more modular and maintainable, the ONBUILD instruction can be a valuable tool in your Docker toolbox.

As with any tool, it's important to use the ONBUILD instruction wisely. Used sparingly and thoughtfully, it can greatly enhance the modularity and reusability of your Docker images. Used excessively or carelessly, it can lead to Dockerfiles that are hard to read and maintain, and behavior that is difficult to predict. As always, the key is to understand the tool and use it appropriately for your specific use case and requirements.

High-impact engineers ship 2x faster with Graph
Ready to join the revolution?
High-impact engineers ship 2x faster with Graph
Ready to join the revolution?

Do more code.

Join the waitlist