This Maven plugin integrates Maven with Docker.
The design goals are:
- Don't do anything fancy.
Dockerfile
s are how you build Docker projects; that's what this plugin uses. They are mandatory. - Make the Docker build process integrate with the Maven build
process. If you bind the default phases, when you type
mvn package
, you get a Docker image. When you typemvn deploy
, your image gets pushed. - Make the goals remember what you are doing. You can type
mvn dockerfile:build
and latermvn dockerfile:tag
and latermvn dockerfile:push
without problems. This also eliminates the need for something likemvn dockerfile:build -DalsoPush
; instead you can just saymvn dockerfile:build dockerfile:push
. - Integrate with the Maven build reactor. You can depend on the Docker image of one project in another project, and Maven will build the projects in the correct order. This is useful when you want to run integration tests involving multiple services.
This project adheres to the Open Code of Conduct. By participating, you are expected to honor this code.
See the changelog for a list of releases
This plugin requires Java 8 or later and Apache Maven 3.5 or later. To run the integration tests or to use the plugin in practice, a working Docker set-up is needed.
For more examples, see the integration test directory.
In particular, the advanced test showcases a full service consisting of two micro-services that are integration tested.
This configures the actual plugin to build your image with mvn package
and push it with mvn deploy
. Of course you can also say
mvn dockerfile:build
explicitly.
<plugin>
<groupId>net.triopsys.docker</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven-version}</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>spotify/foobar</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
A corresponding Dockerfile
could look like:
FROM eclipse-temurin:17-jre-alpine
LABEL maintainer="David Flemström <dflemstr@spotify.com>"
ENTRYPOINT ["java", "-jar", "/usr/share/myservice/myservice.jar"]
# Add Maven dependencies (not shaded into the artifact; Docker-cached)
ADD target/lib /usr/share/myservice/lib
# Add the service itself
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar
Important note
The most Maven-ish way to reference the build artifact would probably
be to use the project.build.directory
variable for referencing the
'target'-directory. However, this results in an absolute path, which
is not supported by the ADD command in the Dockerfile. Any such source
must be inside the context of the Docker build and therefor must be
referenced by a relative path. See spotify#101
Do not use ${project.build.directory}
as a way to reference your
build directory.
There are many advantages to using this plugin for your builds.
This plugin lets you leverage Docker cache more consistently, vastly
speeding up your builds by letting you cache Maven dependencies in
your image. It also encourages avoiding the maven-shade-plugin
,
which also greatly speeds up builds.
You no longer have to say something like:
mvn package
mvn dockerfile:build
mvn verify
mvn dockerfile:push
mvn deploy
Instead, it is simply enough to say:
mvn deploy
With the basic configuration, this will make sure that the image is built and pushed at the correct times.
You can depend on the Docker information of another project, because this plugin attaches project metadata (Docker Info JAR) when it builds Docker images. Simply add this information to any project:
<dependency>
<groupId>com.spotify</groupId>
<artifactId>foobar</artifactId>
<version>1.0-SNAPSHOT</version>
<type>docker-info</type>
</dependency>
Now, you can read information about the Docker image of the project that you depended on:
String imageName = getResource("META-INF/docker/com.spotify/foobar/image-name");
This is great for an integration test where you want the latest version of another project's Docker image.
Note that you have to register a Maven extension in your POM (or a
parent POM) in order for the docker-info
type to be supported:
<build>
<extensions>
<extension>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-extension</artifactId>
<version>${version}</version>
</extension>
</extensions>
</build>
Your project(s) look like so:
a/
Dockerfile
pom.xml
b/
Dockerfile
pom.xml
You can now use these projects with Fig or docker-compose or some
other system that works with Dockerfiles. For example, a
docker-compose.yml
might look like:
service-a:
build: a/
ports:
- '80'
service-b:
build: b/
links:
- service-a
Now, docker-compose up
and docker-compose build
will work as
expected.
See usage docs.
See authentication docs.
To cut the Maven release:
mvn clean [-B -Dinvoker.skip -DskipTests -Darguments='-Dinvoker.skip -DskipTests'] \
-Dgpg.keyname=<key ID used for signing artifacts> \
release:clean release:prepare release:perform
We use gren
to create Releases in Github:
gren release