For local development I'd like to copy a maven war package into a docker container right after mvn package has created the package. How can I accomplish this?
My workflow as of right now is with a specific dockerid:
$ mvn clean package
$ docker cp the.war dockerid:/usr/local/tomcat/webapps/the.war
A Tomcat server in the docker container recognizes the new war and starts again.
I tried adding the maven-antrun-plugin. However, the war is not deployed, whether I use it in the install or package phase. I get no error or warning with e.g. mvn clean package. However, the.war file is not copied into the docker container.
Below the dockerid is hardcoded momentarily.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.jdk>1.8</version.jdk>
<version.maven.compiler>3.6.1</version.maven.compiler>
...
</properties>
...
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<configuration>
<target>
<exec executable="docker">
<arg value="cp"/>
<arg value="${basedir}/target/the.war"/>
<arg value="dockerid:/usr/local/tomcat/webapps/the.war"/>
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
Related
I have a microservices project with a parent POM and all the other modules with an internal POM.
Locally, if I run mvn clean install -DskipTests everything works.
I want to deploy all the microservices to Heroku, how can i do this?
The project works also for Docker & Kubernetes, is there a way to integrate also Docker in Heroku?
So it will be beautiful if I can deploy all the microservices as 1 project in Heroku, with every microservices as a Docker image.
Thank you in advance!
This is an example of my project:
Parent POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.petcare</groupId>
<artifactId>website-petcare-backend</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>parent-pom</name>
<modules>
<module>apiGateway</module>
<module>reservationService</module>
<module>userService</module>
<module>eurekaServer</module>
<module>mapService</module>
<module>authService</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Build
You can build all images for the sub-modules using the docker-maven-plugin.
Each sub-module must have its own Dockerfile, then in the parent POM add:
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.38.1</version>
<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>build</goal>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
When running mvn clean package docker:build all projects are built and Dockerized
Deploy
Deploying all images (each image into its own web Dyno) is a little bit more complicated. You have few options:
Script from the command line: typically you can push the image with the following commands
heroku container:push web -a appname
heroku container:release web a appname
You could build a script that performs those steps for each and (very important) performs both the heroku login and heroku:container login using the credentials
Using heroku.yml where you can define at once all the containers to be deployed. It is a good approach but you need to git push your changes (see here)
Use CI/CD application like Github Actions. In this case your workflow compiles, tests, builds and pushes the application.
This is my preferred approach: you can decide when to build/deploy (on master push? manually?), you save the Heroku credentials as secrets, you can automate the release pipeline.
You can read more here
You can also try the Heroku Docker Maven plugin if you like to control all services using Maven
I am creating docker image using google's Jib maven plugin, image gets created successfully and backend services are working fine but my webapp folder is not part of that image. Before jib i was creating a zip containing everything (including webapp folder in the root of that zip along with executable jar) which was working fine.
Now the image created by jib has classes, libs, resources in the app root. How and where should i copy webapp folder ?
It worked for me by using external directories provided by maven jib plugin.
<extraDirectories>
<paths>
<path>webapp</path>
<path>
<from>webapp</from>
<into>/app/webapp</into>
</path>
</paths>
</extraDirectories>
I am currently using running a spring-boot version 2.4.10 and the application is packed as a jar.
My project have JSPs at:
src/main/webapp/WEB-INF/jsp
This is important because it allows me to run the application as an executable jar: java -jar ./target/app.jar --spring.profiles.active=prod
jib-plugin doesn't copy the src/main/webapp directory to the container image by default, so we need to add it manually by including the following configuration.
<extraDirectories>
<paths>
<path>
<from>src/main/webapp/WEB-INF</from>
<into>/app/resources/META-INF/resources/WEB-INF</into>
</path>
</paths>
</extraDirectories>
I provide jib-plugin a custom entrypoint.sh
The entrypoint.sh is located at src/main/jib
#!/bin/sh
echo "The application will start in ${APPLICATION_SLEEP}s..." && sleep ${APPLICATION_SLEEP}
exec java ${JAVA_OPTS} -noverify -XX:+AlwaysPreTouch \
-Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* \
"com.demo.application.Application" "$#"
My final jib-plugin configuration is the following:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>${jib-maven-plugin.version}</version>
<configuration>
<from>
<image>adoptopenjdk:11-jre-hotspot</image>
</from>
<to>
<image>myprivateregistry/app/${project.name}</image>
<tags>
<tag>latest</tag>
<tag>${project.version}</tag>
</tags>
</to>
<container>
<entrypoint>
<shell>bash</shell>
<option>-c</option>
<arg>/entrypoint.sh</arg>
</entrypoint>
<ports>
<port>8080</port>
</ports>
<environment>
<SPRING_OUTPUT_ANSI_ENABLED>ALWAYS</SPRING_OUTPUT_ANSI_ENABLED>
<APPLICATION_SLEEP>0</APPLICATION_SLEEP>
</environment>
<creationTime>USE_CURRENT_TIMESTAMP</creationTime>
</container>
<extraDirectories>
<paths>
<path>src/main/jib</path>
<path>
<from>src/main/webapp/WEB-INF</from>
<into>/app/resources/META-INF/resources/WEB-INF</into>
</path>
</paths>
<permissions>
<permission>
<file>/entrypoint.sh</file>
<mode>755</mode>
</permission>
</permissions>
</extraDirectories>
</configuration>
<!-- Make JIB plugin run during the packing life cycle -->
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
The above didn't work for me but the below did.
<extraDirectories>
<paths>
<path>
<from>../path/to/frontend/app/dist</from>
<into>/app/resources/static</into>
</path>
</paths>
</extraDirectories>
If I have a pom.xml with the following code:
<build>
<plugins>
<plugin>
<groupId>something</groupId>
<artifactId>XXX</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
</plugins>
</build>
When I run mvn clean package, I want to run that plugin(which actually runs).
but
If I run mvn clean deploy, given phase package is previous to phase deploy is gonna run either(which I don't want to).
Is there any way to not run this plugin during deploy?
By the way: I cannot modify the mvn command executed, I need to do this inside the pom.xml file
The only way that I know to selectively enable a plugin is through Maven profile:
<project ...>
...
<build>
...
</build>
<profiles>
<profile>
<id>someprofile</id>
<build>
<plugins>
<plugin>
<groupId>something</groupId>
<artifactId>XXX</artifactId>
...
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
You would then run mvn package -Psomeprofile to run the plugin, or mvn deploy to not run it.
There are additional ways to automatically activate a profile. You will have to read the docs to see if any of those apply to you.
I am trying to integrate maven dockerfile plugin with my project. I have multiple modules under my maven project. I have modified the pom.xml for the module I want to build and tag images as below. Running mvn dockerfile:build command builds a creates a docker-info.jar under the target folder. I am not sure where the images are being built and when I try to run the mvn dockerfile:tag command I see the below error.
Failed to execute goal com.spotify:dockerfile-maven-plugin:1.4.4:tag
(default-cli) on project drs-web: The parameters 'repository' for goal
com.spotify:dockerfile-maven-plugin:1.4.4:tag are missing or invalid
Pom.xml:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${docker.maven.plugin.version}</version>
<executions>
<execution>
<id>build</id>
<goals>
<goal>build</goal>
</goals>
<configuration>
<buildArgs>
<WAR_FILE>${project.build.finalName}.war</WAR_FILE>
</buildArgs>
</configuration>
</execution>
<execution>
<id>tag</id>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<repository>XXX/XXX-api</repository>
<tag>${project.version}</tag>
</configuration>
</execution>
</executions>
</plugin>
Dockerfile:
FROM tomcat:9.0.10-jre8-slim
ENV CATALINA_HOME /usr/local/tomcat
MAINTAINER XXX
EXPOSE 8080
ADD target/${WAR_FILE} ${CATALINA_HOME}/webapps/XXX-api.war
To fix the error you should use the same parameters in two sections of your pom.xml. You didn't define the repository's name for the build goal:
<configuration>
<repository>XXX/XXX-api</repository>
</configuration>
The fact that docker-info.jar was created in your Target directory most likely means that the creation of the docker image completed successfully.
The image should be put to your Docker registry with the name "XXX/XXX-api", and you can check it from a console with the command:
docker image ls
P.S. You can avoid generation of docker-info.jar by adding the following parameter to the configuration section of dockerfile-maven-plugin:
<configuration>
<skipDockerInfo>true</skipDockerInfo>
</configuration>
I would like to find out the values of all Maven properties as they apply to some Maven project.
mvn help:system lists OS environment variables and JVM system properties, but no Maven properties.
mvn help:evaluate only works in an interactive mode, that means I have to type a single Maven property, (e.g. ${project.build.outputDirectory}) to get the value of that property.
I'm looking for a way get a full list of all Maven properties and their values.
As a workaround, add this to the <plugins> ... </plugins> section inside your project's pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echoproperties />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
Now execute mvn validate.
On the console, prefixed with [echoproperties], there will be the full list of system properties, including those set by Maven such as project.build.outputDirectory, basedir, and settings.localRepository.
the maven-help-plugin does what you want, just call it with -Dexpression=project.properties this will print the properties tag of the effective pom.
mvn help:evaluate -Dexpression=project.properties
Bonus Points when you just want the properties output and not the maven output
mvn help:evaluate -Dexpression=project.properties -q -DforceStdout
or with the explicit version because -DforceStdout works since version 3.1.0
mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.properties -q -DforceStdout
Not sure if helps, but I found this when trying to do the same thing:
mvn com.github.ekryd.echo-maven-plugin:echo-maven-plugin:echo -Decho.message='${project.build.testOutputDirectory}'
From here.
Adding the following to ${user.home}/.m2/settings.xml:
<pluginGroups>
<pluginGroup>com.github.ekryd.echo-maven-plugin</pluginGroup>
</pluginGroups>
the command can be shortened to:
mvn echo:echo -Decho.message='${project.build.testOutputDirectory}'
I don't know how to get them "officially", but here is a workaround. Add maven-antrun-plugin to your project and run mvn test -X. The plugin will show all properties passed to it from Maven. The list looks complete to me.
Actually project.build.outputDirectory is there but you need to execute in 'compile' phase, and NOT in 'validate'. I guess what properties are available also depends on the current phase for the executing goal of a particular plug-in, in this case 'maven-antrun-plugin'.
<!-- Ant Run Plugin for debugging pom.xml and calling ant tasks -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>${ant.plugin.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echoproperties/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
Had the same issue. Changed the timeout and maxheap in findbugs configuration through maven.
The below fixed it for me :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<maxHeap>2048</maxHeap>
<timeout>1800000</timeout>
</configuration>
</plugin>