How to use Spotify Docker Maven plugin

Have you ever wondered how to build and push a docker image from your Maven plugins? Well, if you are looking for such a thing, you are in the right place. In this tutorial, we cover how to use the Spotify docker maven plugin (dockerfile-maven-plugin to be more specific), in any Maven project.

Spotify has two Maven plugins that allow you to build and push a docker image within the Maven life cycle. The older plugin which is docker-maven-plugin is currently unmaintained and nobody should use it. The newer plugin which is dockerfile-maven-plugin is what we cover in this tutorial.

Note: as of September 2021, both of the Spotify plugins are unmaintained and archived. It is recommended to use either the built-in Spring Boot functionality or the docker command to build Docker images.

Before continuing this tutorial, We’d like to shortly mention the motivation behind this tutorial. When we were trying to work with the new Spotify Maven plugin, we realized that there was not much official documentation, to begin with. With no surprise, the majority of the StackOverflow responses cover only the older plugin. Hence, we had an extremely hard time configuring my project to use the plugin to just push a simple docker image to Docker Hub. That is why once we spent some time and figured out most of the stuff, decided to write this article with the aim of anyone who has a hard time configuring the plugin.

Without further ado let’s get started.

Adding the Spotify Docker Maven plugin to pom.xml

The first thing we have to do is to add the Spotify plugin to our maven pom.xml file. It is relatively simple,

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.10</version>
            <executions>
                <execution>
                    <id>tag-latest</id>
                    <goals>
                        <goal>build</goal>
                        <goal>tag</goal>
                        <goal>push</goal>
                    </goals>
                    <configuration>
                        <tag>latest</tag>
                    </configuration>
                </execution>
                <execution>
                    <id>tag-version</id>
                    <goals>
                        <goal>build</goal>
                        <goal>tag</goal>
                        <goal>push</goal>
                    </goals>
                    <configuration>
                        <tag>${project.version}</tag>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Keep in mind that this configuration is not finalized yet. We will revisit it later. That is to just get us started.

In the above configuration, we have two executions (tag-latest, tag-version). That is important if we want to have the latest docker tag and have it updated. In other words, whenever the plugin pushes a Docker image, it tags the image as what is set in the version of pom.xml as well as the latest. This way latest tag always be the same as the latest Docker tag available.

Creating Docker file

Now that we have our plugin configured, we need to create a Dockerfile so that the plugin builds the image based on that. The docker file does not need to have any extra bells and whistles. It is just a normal docker file like this,

FROM adoptopenjdk/openjdk11:x86_64-ubuntu-jdk-11.0.3_7

MAINTAINER Name <[email protected]>

RUN mkdir -p /user/share/[artifactId]/static/songs

RUN mkdir -p /user/share/[artifactId]/bin

ADD /target/[artifactId]*SNAPSHOT.jar /user/share/cisapify/bin/[artifactId].jar

WORKDIR /user/share/[artifactId]

ENTRYPOINT ["/opt/java/openjdk/bin/java", "-jar", "bin/[artifactId].jar"]

This Dockerfile should be located at the root of the project so that the plugin can pick it up automatically.

Build the image for the first time

We have all the basic configurations ready. It is time to build the image for the first time and run it locally to see how it works. To do so, we can use mvn with some parameters,

$ mvn dockerfile:build

Or

$ mvn clean package

Once the docker image is built successfully, we can try to run it like,

$ docker run -p [8080:8080] # port assume having web app [image name]:[tag]

After ensuring everything is up and running smoothly, it’s time to move to the next step, pushing the image to Docker Hub

Pushing the image to Docker Hub (registry)

In order to push the image to Docker Hub, we should revisit pom.xml and add some extra configuration to the plugin. This configuration consists of the URL of the registry that we want to push, tag and build the argument.

<build>
    <plugins>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.10</version>
            <executions>
                <execution>
                    <id>tag-latest</id>
                    <goals>
                        <goal>build</goal>
                        <goal>tag</goal>
                        <goal>push</goal>
                    </goals>
                    <configuration>
                        <tag>latest</tag>
                    </configuration>
                </execution>
                <execution>
                    <id>tag-version</id>
                    <goals>
                        <goal>build</goal>
                        <goal>tag</goal>
                        <goal>push</goal>
                    </goals>
                    <configuration>
                        <tag>${project.version}</tag>
                    </configuration>
                </execution>
            </executions>
            <configuration>
                <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
                <repository>registry.hub.docker.com/[username]/${project.artifactId}</repository>
                <tag>${project.version}</tag>
                <buildArgs>
                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                </buildArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

Keep in mind to replace [username] with your username. Otherwise, it will not work.

Since we want to push the image to a public repository, we need to do authentication. For that, we highly recommend keeping the credentials in a separate file to avoid mixing things up. The ideal approach is to keep them in the ~/.m2/settings.xml file. However, that needs an extra flag, useMavenSettingsForAuth, in our configuration which is given in the above configuration.

Obviously, the last step is to create a settings.xml under the ~/.m2 path and add the Docker Hub credentials. Here, I add an example that you just need to replace username, password, and email.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                          https://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>registry.hub.docker.com</id>
            <username>USERNAME</username>
            <password>PASSWORD</password>
            <configuration>
                <email>EMAIL_ADDRESS</email>
            </configuration>
        </server>
    </servers>
</settings>

Once that’s finished, we can try to push the image to Docker Hub by running,

$ mvn dockerfile:push

Or

$ mvn clean deploy

To ensure everything is working, just check the https://cloud.docker.com/ and should see your newly created tag there. Something like this image.

docker-tag

Conclusion

In this tutorial, we discussed how to use the Spotify Docker Maven plugin to build a Docker image for a Spring Boot application. The plugin provides a way to publish Docker images to Docker Hub with simple configurations.

You can always find more Docker content on this site at the link below:
https://geekyhacker.com/?s=docker

Inline/featured images credits