It’s hard to ignore Docker nowadays. There are a lot of blog posts available on the Web. The problem is that most always repeat the same. In this post, I’d like to focus on one directive that I find overlooked via a use-case: it is Java specific, but the parallel can be easily drawn to other tech stacks.
The problem
The situation is the following: as a developer, I’d like to use Docker as a way to package a JAR from the sources of my application.
As a reminder, here’s a sample Maven structure:
|__ src | |__ main | |__ java | |__ Application.java | |__ resources | |__ application.properties |__ pom.xml
With Docker, this is as easy as creating a Dockerfile that inherits from the Maven image:
FROM maven:3.6.0-alpine (1)
WORKDIR app (2)
COPY . /app (3)
RUN mvn package (4)
1 | Start from one of the official Maven image on Dockerhub |
2 | Set the working directory to app |
3 | Copy the current host directory to the image app folder |
4 | Build the JAR |
This works as expected.
Now, let’s imagine I’d need to package several such apps. All Dockerfiles will follow the same structure as above. That contradicts the DRY principle.
The solution
Among the many directives available in the syntax of Dockerfiles is the ONBUILD
one.
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 theFROM
instruction in the downstreamDockerfile
.
https://docs.docker.com/engine/reference/builder/#onbuild
The gist of it is that it reverses the standard approach:
in lieu of Dockerfile explicitly adding files and running commands, ONBUILD
provides a canvas so that one just need to fill out the blanks.
Let’s create such a "parent" Dockerfile.
FROM maven:3.6.0-alpine
WORKDIR app
ONBUILD COPY . /app
ONBUILD RUN mvn package
From this file, it’s possible to create the image:
docker build -f maven.Dockerfile -t mavenbase .
This doesn’t require any project but the Dockerfile itself. |
At any later point in time, from any Maven-compliant folder structure, it’s possible to create a thinned-down Dockerfile
and build the app using the build image:
FROM mavenbase:latest (1)
1 | Yes, only a single directive necessary! |
docker build -f app.Dockerfile -t myapp .
Conclusion
Beyond simple usages, Docker allows offers a wide range of features.
Among them, the ONBUILD
directive allows to drastically reduce Dockerfile size by factoring repetitive configuration in a parent image.