<img alt="" src="https://secure.leadforensics.com/149263.png" style="display:none;">
hero wave

Local Builds: Building a Java Project with Docker

That Time a Script Erased My System 

In my previous post, Local Builds: Building with Docker, I provided a real-life example of why it’s important to use Docker with local builds.  For those just joining in, during my first week at a new job, the build scripts provided by the development team erased my system. 

It turned out that everyone in my team had only built using Eclipse on Windows and had never built the product on Linux outside of a Jenkins environment. As a result, the script assumed that the WORKSPACE environment variable was set. Instead of taking advantage of the built-in facilities for clearing the workspace, it had a manual, recursive deletion step. Consequently, the script changed to the root of my file system and recursively deleted everything in my system. 

Including a build script in a project repository ensures that each member of a developer team will have the same experience building (whether it is on Linux, Mac OS or Windows under WSL2) because, Docker builds and executes the same on each platform. The following is a sample Bash script that will build a Java project. 

Sample Docker Build 

#!/usr/bin/env bash 

docker run --rm \ 

-i -t \ 

--volume ${PWD}:/tmp/app/ \ 

--workdir /tmp/app/ \ 

--volume ~/.m2/:/tmp/.m2/ \ 

--user `id -u`:`id -g` \ 

-e MAVEN_CONFIG=/tmp/.m2 \ 

maven:3.6.3-jdk-11 \ 

sh -c 'mvn clean install -am -U \ 

-Dmaven.repo.local=/tmp/.m2/repository/ \ 

-Duser.home=/tmp' 

Breaking down the build 

Step 1:  

Run the container and remove it once the build is complete. 

docker run –rm 

This is the image used to perform the build. It is the key to ensuring a consistent build across platforms. 

maven:3.6.3-jdk-11 

Step 2:  

Use an interactive terminal, allowing the build to be cancelled via Ctrl+C. . This will often fail in a headless environment, such as Jenkins, due to the lack of a TTY and can be omitted in those environments without otherwise impacting the consistency of a build. 

-i -t  

Step 3:  

Use the current directory as the mount point for the root of the build. 

--volume ./:/tmp/app/ 

--workdir /tmp/app/ 

 

Step 4:

Mount and use the current user’s .m2 directory, allowing the build to use and install locally built libraries. This is especially necessary when developing support libraries for larger projects. 

--volume ~/.m2/:/tmp/.m2/ 

-e MAVEN_CONFIG=/tmp/.m2 

-Dmaven.repo.local=/tmp/.m2/repository/ 

-Duser.home=/tmp' 

Step 5: 

Run the build as the current user. Without this step, all files built and created will be owned by root. 

--user `id -u`:`id -g` 

Bring It All Together 

Visit our GitHub repository for build examples covering other languages: click here to visit CodeLogic's GitHub repository.

With a simplified build environment, new developers won’t need to run down the rabbit hole of reading a multi-page wiki on how to setup a local build environment as I did. Instead, they can find all that they need in a few lines with the project’s README.  

However, the main benefit in my opinion, is that they can confidently build, knowing it won’t delete everything on their local file system as it did my first week at a new job. 

graphic-CTA-mockups

Want to learn more?

Sign up for a free trial today.

Want to learn more about dependency mapping?

Browse Blog