Suppose you want to build a java maven project, but you don't have the correct environment to do so. Or you just don't want to mess up your local machine. You can use docker to do the build without installing JDK or Maven.

We are going to use Spring PetClinic application as a sample for this post. Let's start by checking out the sources from github.

git clone https://github.com/spring-projects/spring-petclinic.git

Change into the directory.

cd spring-petclinic

Now for the magic part:

docker run -it --rm -v "$PWD":/work -w /work \
  maven:3.3.9-jdk-7 mvn package

Here we are running the maven docker image maven:3.3.9-jdk-7. You can choose different java and maven versions from the docker repository according to your project needs. We also added the current directory as a volume mounted to /work.

Docker command will take some time to complete. It will get the container image first, if its not downloaded before. The container just runs mvn package when the image is downloaded and started. Than maven will fetch all its dependencies, run the tests and build the project artifacts. petclinic.war in this case. After the build is complete the container will exit and remove itself (-rm) from the docker server.

Build results will be inside the target directory on your local file system:

$ ls -1 target/
classes
generated-sources
generated-test-sources
maven-archiver
maven-status
petclinic
petclinic.war
surefire-reports
test-classes

Persistent Maven Repository

Above procedure can be optimized by making the maven repository persistent between further runs. You'll save loads of time and bandwith by not downloading all the dependencies for every build.

Docker volumes to the rescue.

docker volume create --name m2repo

And add this volume when running the container.

docker run -it --rm -v "$PWD":/work -v m2repo:/root/.m2 -w /work \
  maven:3.3.9-jdk-7 mvn package

only difference here is the second -v parameter that maps the volume we just created to /root/.m2 directory.

This optimization dropped the build time to 90 seconds from 200 seconds on my old mac with a decent network.