After reading the article about packaging
JVM applications in Docker , I was confused. I, like any developer, want
my hair to fly in the wind, the container was going to be for one team, immediately, without any extra gestures. That the project and assembly configuration was collected in one file, and that there were no dependencies on external systems.

An alternative way to build Java applications in a Docker container using Maven will follow.
To build, we need a Java project, Maven, and a little patience to get it all.
')
DisclaimerI assume that the reader is already familiar with Java, Maven and Docker. Represents what is written in the Docker-file, why does he need all this and generally ninja
This time, we will use the Maven plugin from
fabric8io .
Suppose that we have a micro service that is packaged in a jar file containing the main method, which must be run to start the application. Add a plugin to the build section:
<plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.16.4</version> <executions> <execution> <id>Build docker container</id> <phase>package</phase> <goals> <goal>build</goal> </goals> </execution> <execution> <id>Push docker container</id> <phase>deploy</phase> <goals> <goal>push</goal> </goals> </execution> </executions> <configuration> <images> <image> <name>${project.artifactId}</name> <registry>registry.io</registry> <build> <from>java:8</from> <tags> <tag>${project.version}</tag> </tags> <ports> <port>8080</port> </ports> <cmd> <shell>java -cp 'jars/*' com.myapp.MainClass '/config.file'</shell> </cmd> <assembly> <basedir>/</basedir> <inline> <dependencySet> <outputDirectory>jars</outputDirectory> </dependencySet> <files> <file> <source>${project.build.directory}/${project.build.finalName}.jar</source> <outputDirectory>jars</outputDirectory> </file> <file> <source>${project.basedir}/src/main/config/config.yml</source> <outputDirectory>/</outputDirectory> </file> </files> </inline> </assembly> </build> </image> </images> </configuration> </plugin>
And, in general, that is all. Let us examine in more detail what is written there.
At the beginning there is a typical definition of a plugin with a version. Next comes the definition of which phases of the
moon assembly we want to assemble and push our container. In my case, the container will be built during the project packaging (phase: package).
Pushing the container to the repository will occur during the deploy phase.
<executions> <execution> <id>Build docker container</id> <phase>package</phase> <goals> <goal>build</goal> </goals> </execution> <execution> <id>Push docker container</id> <phase>deploy</phase> <goals> <goal>push</goal> </goals> </execution> </executions>
Attention Maven!Maven has a beastly habit of running different plugins of the same phase in order to mention them in effective pom. You can build an effective pom with the following command:
mvn help:effective-pom
If you can’t get the right order by any tricks, then move the container building to the next phase: install, deploy.
For example, in my case, transfer to the deploy phase looks like this:
<executions> <execution> <id>Build & Push docker container</id> <phase>deploy</phase> <goals> <goal>build</goal> <goal>push</goal> </goals> </execution> </executions>
Define the image name and repository:
<name>${project.artifactId}</name> <registry>registry.io</registry>
If the repository is not specified, the Docker repository will be used.
Documentation for further reading.
Description of the image build is carried out in the <build> section. This is essentially a reflection of the Docker file in Maven.
from - base image
tags - tags with which the image will be collected
ports - open ports
cmd is a launch line, you can also specify entryPoint, all available options can be read in the documentation .
In my example:
<shell>java -cp 'jars/*' com.myapp.MainClass '/config.file'</shell>
This is a typical Java application launch string, wrapped in a Docker's shell form, in the Maven view.
assembly is the most interesting part of the plugin. It determines what will be packaged in a container image and how. There are several options for how to describe the packaging, I chose inline, but there are other
options .
In the example, I want to take all the dependencies of the project and put it in the jars folder:
<dependencySet> <outputDirectory>jars</outputDirectory> </dependencySet>
And also, the artifact of the project, actually our application, to the same, and the configuration file to the root of the container.
<files> <file> <source>${project.build.directory}/${project.build.finalName}.jar</source> <outputDirectory>jars</outputDirectory> </file> <file> <source>${project.basedir}/src/main/config/config.file</source> <outputDirectory>/</outputDirectory> </file> </files>
Learn more about the assembly capabilities in the
documentation , this time Maven.
And that's it! As a result:
- The entire configuration of the Docker container assembly is concentrated in the project file.
- We can use all the advantages of Maven, its variables and plugins.
- The container is assembled transparently, at the time of the project assembly, the result is available locally.
- Container versioning goes hand in hand with our project.
- We can continue to use the same CI / CD tool as before (you need to install Docker on the server).
A few words about the plugin: development is active, the maintainer promptly responds and willingly merjit pool requests.
"The plugin itself can do much more:
features»Sample project posted on
github-e