Dockerfile ONBUILD instruction

Docker

Docker Problem Overview


I read on the docker documentation how ONBUILD instruction can be used, but it is not clear at all.
Can someone please explain it to me?

Docker Solutions


Solution 1 - Docker

The ONBUILD instruction is very useful for automating the build of your chosen software stack.

Example

The Maven container is designed to compile java programs. Magically all your project's Dockerfile needs to do is reference the base container containing the ONBUILD intructions:

FROM maven:3.3-jdk-8-onbuild
CMD ["java","-jar","/usr/src/app/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]

The base image's Dockerfile tells all

FROM maven:3-jdk-8

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ONBUILD ADD . /usr/src/app

ONBUILD RUN mvn install

There's a base image that has both Java and Maven installed and a series of instructions to copy files and run Maven.

The following answer gives a Java example

Solution 2 - Docker

As stated by the docker docs:

> The ONBUILD instruction adds to the image a trigger instruction to be executed at a later time, when the image is used as the base for another build. The trigger will be executed in the context of the downstream build, as if it had been inserted immediately after the FROM instruction in the downstream Dockerfile.

So what does that mean? Let's take this Nodejs Dockerfile:

FROM node:0.12.6

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ONBUILD COPY package.json /usr/src/app/
ONBUILD RUN npm install
ONBUILD COPY . /usr/src/app

CMD [ "npm", "start" ]

In your own Dockerfile, when you do FROM node:0.12.6-onbuild you're getting an image, which means the build command has already been run, so the instructions have ALREADY been executed as well, however all but those starting with ONBUILD. These have been deferred to another time, when the downstream build (when your image is getting built from your own Dockerfile) uses this image as the base (FROM node:0.12.6-onbuild).

> You can’t just call ADD and RUN now, because you don’t yet have access to the application source code, and it will be different for each application build.

That's right! The image containing onbuild instructions wasn't built on your machine, so it doesn't yet have access to package.json.

Then when you build your own Dockerfile, before executing any instruction in your file, the builder will look for ONBUILD triggers, which were added to the metadata of the parent image when it was built.

That spares you the hassle of executing these commands yourself, it really is as though these commands were written in your own Dockerfile.

Finally, they add:

> You could simply provide application developers with a boilerplate Dockerfile to copy-paste into their application, but that is inefficient, error-prone and difficult to update because it mixes with application-specific code.

The thing is that if these instructions are modified in the boilerplate Dockerfile, you will have to modify them as well in your Dockerfile. But thanks to the ONBUILD instruction, we don't have to worry about it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsoftshipperView Question on Stackoverflow
Solution 1 - DockerMark O'ConnorView Answer on Stackoverflow
Solution 2 - DockerjperlView Answer on Stackoverflow