Spotify Docker Maven plugin changes
By John Carnell
This article discusses some changes made by the Spotify Docker Maven plugin team.
One of the challenges with writing a technology book, especially one that deals with a number of development frameworks, is that things can change rapidly. Throughout the year and half, I spent writing Spring Microservices in Action I encountered this repeatedly.
Shortly after the publication of the book, a couple of my readers contacted me to let me know that the Spotify team was deprecating their Docker Maven plugin. This does not mean the code is being pulled from their Github repository. It just means the Spotify team will not being doing any more active development with the plugin. It also means that the code examples in the book will continue to function on most of the major platforms (with may be the exception of a Raspberry Pi. One of the readers who reported the issue uncovered it while trying to build my code examples on a Raspberry Pi.)
I appreciate the time and effort the Spotify team put in building the plugin. I also respect their decision to move forward with a new plugin design. The new plugin, called dockerfile-maven, is located here.
As such, I took chapter 1 from the book and branched the code using the tag DOCKERFILE-MAVEN. The Spotify team’s goal with the new plug-in was to streamline the plugin and have it fit more with the standard Maven build lifecycle. I am not going into a significant amount of detail around the plugin, but I did want to walkthrough an example how to setup and use it in your services and in the code examples in the book.
The new plug-in also introduced several new efficiencies into the overall Docker/Maven build process.
So, what changed:
1. The general structure of the dockerfile-maven build plugin
2. Where the Dockerfile is located
3. Parameter values in the Docker file
The general structure of the dockerfile-maven build plugin
Let’s begin by looking at the Maven pom.xml I put together for the Chapter 1 simpleservice.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.thoughtmechanix</groupId>
<artifactId>simple-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging><name>Simple Service</name>
<description>Simple Service</description><parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.4.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies><properties>
<project.build.sourceEncoding>
UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<project.build.sourceEncoding>
UTF-8</project.build.sourceEncoding>
<start-class>
com.thoughtmechanix.simpleservice.Application
</start-class>
<docker.image.name>
johncarnell/tmx-simple-service</docker.image.name>
<docker.image.tag>chapter1</docker.image.tag>
</properties><build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--This is the new spotify plugin-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.4</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
<execution>
<id>tag</id>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<repository>${docker.image.name}</repository>
<tag>${docker.image.tag}</tag>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
The key code in the Maven pom.xml shown above is highlighted. The key thing to note here is that the dockerfile-maven plugin hooks directly into the Maven build lifecycle. This means that unlike the previous docker-maven plugin where you needed to issue a mvn clean package docker:build to perform a build and create a Docker image of the service, you now just need to issue a standard mvn package command.
The second thing you will notice with the new plugin is that you no longer have to copy your final executable jar from the service’s target directory to the directory where your Dockerfile is located. This eliminates a rather large and annoying step in the pom.xml that would place an executable JAR in essentially a source directory.
Where the Dockerfile is located
One of the Spotify dockerfile-maven team’s goals was having all image preparation steps happen inside the Dockerfile. In the old plugin, you could put the Dockerfile for the service in any directory you wanted, but then had to jump through hoops to make sure that any files you wanted placed on your Docker image had to be copied to the director where Dockerfile was located. With the new plugin, your Dockerfile has to be at the same level as your pom.xml. This avoids having to do all of the file copying work you saw with the previous Spotify Docker/Maven plugin.
The Dockerfile from the Chapter 1 simpleservice reflects this:
FROM openjdk:8-jdk-alpine
RUN apk update && apk upgrade && apk add netcat-openbsd
RUN mkdir -p /usr/local/simple-service
ADD target/simple-service-0.0.1-SNAPSHOT.jar /usr/local/simple-service
ADD src/main/docker/run.sh run.sh
RUN chmod +x run.sh
CMD ./run.shThe bolded statements in the code example above reflect this. By putting the Dockerfile at the root level of the project, the new dockerfile-maven plugin let’s all of the copying work for the project happen in the Dockerfile instead of in the Maven pom.xml file.
Parameters in the Docker file
One annoyance I did encounter with the new plugin is that is does not seem to honor the Maven environment variables that I used to do name replacement in my various file. So, for example, with the previous plugin I could have used the following code to parameterize the name of the name of the executable JAR being created in my Dockerfile.
FROM openjdk:8-jdk-alpine
RUN apk update && apk upgrade && apk add netcat-openbsd
RUN mkdir -p /usr/local/licensingservice
ADD @project.build.finalName@.jar /usr/local/licensingservice/
ADD run.sh run.sh
RUN chmod +x run.sh
CMD ./run.shThis no longer seems to work and I had to resort to hardcoding the jar name into the file. This might not be an issue with the plugin, but instead my own lack of knowledge around Maven. (This is the point where I sheepishly grin and say sometimes I only understand enough of Maven to get my code to build).
If any reader figures out a way to do this parameterization, I will be more than happy to use it and apply accreditation.
Next steps and the book
So here is my plan. I am going to go through and create a branch for Chapters 1–9 that will reflect using the new plugin. (It might take me a couple of weeks so be patient.) The branch will be called DOCKERFILE-MAVEN. I will also update the READMEs for this chapter to post to this blog post. I will not be merging these changes into the master for the book chapters, because I want the written text to match the code examples as closely as possible.
That’s all for this article. For more information, download the free first chapter of Spring Microservices in Action and see this Slideshare presentation.

