I am new to Docker, and don't know how to run a java project with maven even though i have read many documents and tried many methods.
- Should i build the image using
Dockerfile
?
- What is the commands like when it is to run the maven project in the host with
Dockerfile
?
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.
Update (2018-04-06)
The "--link" option in Docker has been deprecated. To leverage Docker's native DNS you can run the above example as follows
#
# Create a common container network
#
docker network create build
#
# Run the containers on this network
#
docker run -d --network build -p 8081:8081 --name nexus sonatype/nexus
docker run -it --rm --network build \
-v "$(pwd)":/opt/maven \
-w /opt/maven \
maven:3.2-jdk-7 \
mvn -s settings.xml clean install
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:8
EXPOSE 8080
ADD /target/demo.jar demo.jar
ENTRYPOINT ["java","-jar","demo.jar"]
Navigate to the project folder and type following command you will be ab
le 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 update
RUN yum -y install wget tar
# Oracle Java 7
WORKDIR /opt
RUN 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.gz
RUN tar xzf server-jre-7u71-linux-x64.tar.gz
RUN rm -rf server-jre-7u71-linux-x64.tar.gz
RUN alternatives --install /usr/bin/java java /opt/jdk1.7.0_71/bin/java 1
# App
USER daemon
# This copies to local fat jar inside the image
ADD /local/path/to/packaged/app/appname.jar /app/appname.jar
# What to run when the container starts
ENTRYPOINT [ "java", "-jar", "/app/appname.jar" ]
# Ports used by the app
EXPOSE 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 Dockerfile
docker 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.