How to dockerize maven project? and how many ways to accomplish it? How to dockerize maven project? and how many ways to accomplish it? docker docker

How to dockerize maven project? and how many ways to accomplish it?


Working example.

This is not a spring boot tutorial. It's the updated answer to a question on how to run a Maven build within a Docker container.

Question originally posted 4 years ago.

1. Generate an application

Use the spring initializer to generate a demo app

https://start.spring.io/

enter image description here

Extract the zip archive locally

2. Create a Dockerfile

## Build stage#FROM maven:3.6.0-jdk-11-slim AS buildCOPY src /home/app/srcCOPY pom.xml /home/appRUN mvn -f /home/app/pom.xml clean package## Package stage#FROM openjdk:11-jre-slimCOPY --from=build /home/app/target/demo-0.0.1-SNAPSHOT.jar /usr/local/lib/demo.jarEXPOSE 8080ENTRYPOINT ["java","-jar","/usr/local/lib/demo.jar"]

Note

  • This example uses a multi-stage build. The first stage is used to build the code. The second stage only contains the built jar and a JRE to run it (note how jar is copied between stages).

3. Build the image

docker build -t demo .

4. Run the image

$ docker run --rm -it demo:latest  .   ____          _            __ _ _ /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/  ___)| |_)| | | | | || (_| |  ) ) ) )  '  |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::        (v2.1.3.RELEASE)2019-02-22 17:18:57.835  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication v0.0.1-SNAPSHOT on f4e67677c9a9 with PID 1 (/usr/local/bin/demo.jar started by root in /)2019-02-22 17:18:57.837  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default2019-02-22 17:18:58.294  INFO 1 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.711 seconds (JVM running for 1.035)

Misc

Read the Docker hub documentation on how the Maven build can be optimized to use a local repository to cache jars.

Update (2019-02-07)

This question is now 4 years old and in that time it's fair to say building application using Docker has undergone significant change.

Option 1: Multi-stage build

This new style enables you to create more light-weight images that don't encapsulate your build tools and source code.

The example here again uses the official maven base image to run first stage of the build using a desired version of Maven. The second part of the file defines how the built jar is assembled into the final output image.

FROM maven:3.5-jdk-8 AS build  COPY src /usr/src/app/src  COPY pom.xml /usr/src/app  RUN mvn -f /usr/src/app/pom.xml clean packageFROM gcr.io/distroless/java  COPY --from=build /usr/src/app/target/helloworld-1.0.0-SNAPSHOT.jar /usr/app/helloworld-1.0.0-SNAPSHOT.jar  EXPOSE 8080  ENTRYPOINT ["java","-jar","/usr/app/helloworld-1.0.0-SNAPSHOT.jar"]  

Note:

  • I'm using Google's distroless base image, which strives to provide just enough run-time for a java app.

Option 2: Jib

I haven't used this approach but seems worthy of investigation as it enables you to build images without having to create nasty things like Dockerfiles :-)

https://github.com/GoogleContainerTools/jib

The project has a Maven plugin which integrates the packaging of your code directly into your Maven workflow.


Original answer (Included for completeness, but written ages ago)

Try using the new official images, there's one for Maven

https://registry.hub.docker.com/_/maven/

The image can be used to run Maven at build time to create a compiled application or, as in the following examples, to run a Maven build within a container.

Example 1 - Maven running within a container

The following command runs your Maven build inside a container:

docker run -it --rm \       -v "$(pwd)":/opt/maven \       -w /opt/maven \       maven:3.2-jdk-7 \       mvn clean install

Notes:

  • The neat thing about this approach is that all software is installed and running within the container. Only need docker on the host machine.
  • See Dockerfile for this version

Example 2 - Use Nexus to cache files

Run the Nexus container

docker run -d -p 8081:8081 --name nexus sonatype/nexus

Create a "settings.xml" file:

<settings>  <mirrors>    <mirror>      <id>nexus</id>      <mirrorOf>*</mirrorOf>      <url>http://nexus:8081/content/groups/public/</url>    </mirror>  </mirrors></settings>

Now run Maven linking to the nexus container, so that dependencies will be cached

docker run -it --rm \       -v "$(pwd)":/opt/maven \       -w /opt/maven \       --link nexus:nexus \       maven:3.2-jdk-7 \       mvn -s settings.xml clean install

Notes:

  • An advantage of running Nexus in the background is that other 3rd party repositories can be managed via the admin URL transparently to the Maven builds running in local containers.


There may be many ways.. But I implemented by following two ways

Given example is of maven project.

1. Using Dockerfile in maven project

Use the following file structure:

Demo└── src|    ├── main|    │   ├── java|    │       └── org|    │           └── demo|    │               └── Application.java|    │   |    └── test|├──── Dockerfile├──── pom.xml

And update the Dockerfile as:

FROM java:8EXPOSE 8080ADD /target/demo.jar demo.jarENTRYPOINT ["java","-jar","demo.jar"]

Navigate to the project folder and type following command you will be able to create image and run that image:

$ mvn clean$ mvn install$ docker build -f Dockerfile -t springdemo .$ docker run -p 8080:8080 -t springdemo

Get video at Spring Boot with Docker

2. Using Maven plugins

Add given maven plugin in pom.xml

<plugin>    <groupId>com.spotify</groupId>    <artifactId>docker-maven-plugin</artifactId>    <version>0.4.5</version>        <configuration>            <imageName>springdocker</imageName>            <baseImage>java</baseImage>            <entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>            <resources>                <resource>                    <targetPath>/</targetPath>                    <directory>${project.build.directory}</directory>                    <include>${project.build.finalName}.jar</include>                </resource>            </resources>        </configuration>    </plugin>

Navigate to the project folder and type following command you will be able to create image and run that image:

$ mvn clean package docker:build$ docker images$ docker run -p 8080:8080 -t <image name>

In first example we are creating Dockerfile and providing base image and adding jar an so, after doing that we will run docker command to build an image with specific name and then run that image..

Whereas in second example we are using maven plugin in which we providing baseImage and imageName so we don't need to create Dockerfile here.. after packaging maven project we will get the docker image and we just need to run that image..


As a rule of thumb, you should build a fat JAR using Maven (a JAR that contains both your code and all dependencies).

Then you can write a Dockerfile that matches your requirements (if you can build a fat JAR you would only need a base os, like CentOS, and the JVM).

This is what I use for a Scala app (which is Java-based).

FROM centos:centos7# Prerequisites.RUN yum -y updateRUN yum -y install wget tar# Oracle Java 7WORKDIR /optRUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u71-b14/server-jre-7u71-linux-x64.tar.gzRUN tar xzf server-jre-7u71-linux-x64.tar.gzRUN rm -rf server-jre-7u71-linux-x64.tar.gzRUN alternatives --install /usr/bin/java java /opt/jdk1.7.0_71/bin/java 1# AppUSER daemon# This copies to local fat jar inside the imageADD /local/path/to/packaged/app/appname.jar /app/appname.jar# What to run when the container startsENTRYPOINT [ "java", "-jar", "/app/appname.jar" ]# Ports used by the appEXPOSE 5000

This creates a CentOS-based image with Java7.When started, it will execute your app jar.

The best way to deploy it is via the Docker Registry, it's like a Github for Docker images.

You can build an image like this:

# current dir must contain the Dockerfiledocker build -t username/projectname:tagname .

You can then push an image in this way:

docker push username/projectname # this pushes all tags

Once the image is on the Docker Registry, you can pull it from anywhere in the world and run it.

See Docker User Guide for more informations.

Something to keep in mind:

You could also pull your repository inside an image and build the jar as part of the container execution, but it's not a good approach, as the code could change and you might end up using a different version of the app without notice.

Building a fat jar removes this issue.