How to build a docker container for a Java application
Solution 1:
The docker registry hub has a Maven image that can be used to create java containers.
Using this approach the build machine does not need to have either Java or Maven pre-installed, Docker controls the entire build process.
Example
├── Dockerfile
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── org
│ │ └── demo
│ │ └── App.java
│ └── resources
│ └── log4j.properties
└── test
└── java
└── org
└── demo
└── AppTest.java
Image is built as follows:
docker build -t my-maven .
And run as follows:
$ docker run -it --rm my-maven
0 [main] INFO org.demo.App - hello world
Dockerfile
FROM maven:3.3-jdk-8-onbuild
CMD ["java","-jar","/usr/src/app/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]
Update
If you wanted to optimize your image to exclude the source you could create a Dockerfile that only includes the built jar:
FROM java:8
ADD target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar /opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar
CMD ["java","-jar","/opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]
And build the image in two steps:
docker run -it --rm -w /opt/maven \
-v $PWD:/opt/maven \
-v $HOME/.m2:/root/.m2 \
maven:3.3-jdk-8 \
mvn clean install
docker build -t my-app .
__
Update (2017-07-27)
Docker now has a multi-stage build capability. This enables Docker to build an image containing the build tools but only the runtime dependencies.
The following example demonstrates this concept, note how the jar is copied from target directory of the first build phase
FROM maven:3.3-jdk-8-onbuild
FROM java:8
COPY --from=0 /usr/src/app/target/demo-1.0-SNAPSHOT.jar /opt/demo.jar
CMD ["java","-jar","/opt/demo.jar"]
Solution 2:
Structure of java aplication
Demo
└── src
| ├── main
| │ ├── java
| │ │ └── org
| │ │ └── demo
| │ │ └── App.java
| │ └── resources
| │ └── application.properties
| └── test
| └── java
| └── org
| └── demo
| └── App.java
├──── Dockerfile
├──── pom.xml
Content of Dockerfile
FROM java:8
EXPOSE 8080
ADD /target/demo.jar demo.jar
ENTRYPOINT ["java","-jar","demo.jar"]
Commands to build and run image
- Go to the directory of project.Lets say D:/Demo
$ cd D/demo
$ mvn clean install
$ docker build demo .
$ docker run -p 8080:8080 -t demo
Check that container is running or not
$ docker ps
The output will be
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55c11a464f5a demo1 "java -jar demo.jar" 21 seconds ago Up About a minute 0.0.0.0:8080->8080/tcp cranky_mayer
Solution 3:
The easiest way is to let the build tool control the process. Otherwise, you would have to maintain your build tool's build file (like pom.xml
for Maven or build.gradle
for Gradle) as well as a Dockerfile
.
A simple way to build a Docker container for your Java app is to use Jib, which is available as Maven and Gradle plugins.
For example, if you are using Maven and want to build your container to your running Docker daemon, you can just run this one command:
mvn compile com.google.cloud.tools:jib-maven-plugin:0.9.2:dockerBuild
You can also build directly to a Docker registry with Jib without needing to install docker
, run a Docker daemon (which requires root privileges), or write a Dockerfile
. It's also faster and builds images reproducibly.
See more about Jib at its Github repo: https://github.com/GoogleContainerTools/jib