Skip to content

Commit 1cc9da4

Browse files
committed
Initial commit
0 parents  commit 1cc9da4

File tree

8 files changed

+280
-0
lines changed

8 files changed

+280
-0
lines changed

Dockerfile

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Multi-stage build setup (https://docs.docker.com/develop/develop-images/multistage-build/)
2+
3+
# Stage 1 (to create a "build" image, ~140MB)
4+
FROM openjdk:8-jdk-alpine3.7 AS builder
5+
RUN java -version
6+
7+
COPY . /usr/src/myapp/
8+
WORKDIR /usr/src/myapp/
9+
RUN apk --no-cache add maven && mvn --version
10+
RUN mvn package
11+
12+
# Stage 2 (to create a downsized "container executable", ~87MB)
13+
FROM openjdk:8-jre-alpine3.7
14+
WORKDIR /root/
15+
COPY --from=builder /usr/src/myapp/target/app.jar .
16+
17+
EXPOSE 8123
18+
ENTRYPOINT ["java", "-jar", "./app.jar"]

README.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Tutorial: Create a Docker image for a Java application
2+
3+
A template project to create a Docker image for a Java application.
4+
The example application exposes an HTTP endpoint.
5+
6+
The Docker build uses a [multi-stage build setup](https://docs.docker.com/develop/develop-images/multistage-build/)
7+
to minimize the size of the generated Docker image.
8+
9+
10+
# Usage and Demo
11+
12+
**Step 1:** Create the Docker image `miguno/java-docker-build:latest` according to [Dockerfile](Dockerfile).
13+
This step uses Maven to build, test, and package the Java application according to [pom.xml](pom.xml).
14+
15+
```shell
16+
# This may take a few minutes.
17+
$ ./build_image.sh
18+
```
19+
20+
> Example output:
21+
>
22+
> ```
23+
> Building image 'miguno/java-docker-build:latest'
24+
> ...
25+
> Successfully tagged miguno/java-docker-build:latest
26+
> ```
27+
28+
**Step 2:** Start a container for the Docker image.
29+
30+
```shell
31+
$ ./run_image.sh
32+
```
33+
34+
> Example output:
35+
>
36+
> ```
37+
> Starting container for image 'miguno/java-docker-build:latest', exposing port 8123/tcp
38+
> ...
39+
> Endpoint is available at http://0.0.0.0:8123/status
40+
> ```
41+
42+
**Step 3:** Open another terminal and access the example API endpoint.
43+
44+
```shell
45+
$ curl http://localhost:8123/status
46+
{"status": "idle"}
47+
```
48+
49+
50+
# Notes
51+
52+
You can also build, test, and package the Java application locally (without Docker) if you have Maven installed.
53+
54+
```shell
55+
$ mvn package
56+
```

build_image.sh

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
declare -r IMAGE_NAME="miguno/java-docker-build"
4+
declare -r IMAGE_TAG="latest"
5+
6+
echo "Building image '$IMAGE_NAME:$IMAGE_TAG'"
7+
docker build -t $IMAGE_NAME:$IMAGE_TAG .

pom.xml

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>com.miguno</groupId>
8+
<artifactId>java-docker-build</artifactId>
9+
<packaging>jar</packaging>
10+
<version>1.0.0-SNAPSHOT</version>
11+
<name>java-docker-build</name>
12+
13+
<licenses>
14+
<license>
15+
<name>Apache License 2.0</name>
16+
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
17+
<distribution>repo</distribution>
18+
</license>
19+
</licenses>
20+
21+
<properties>
22+
<java.version>8</java.version>
23+
<jersey.version>2.27</jersey.version>
24+
<junit.version>4.12</junit.version>
25+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
26+
</properties>
27+
28+
<dependencyManagement>
29+
<dependencies>
30+
<dependency>
31+
<groupId>org.glassfish.jersey</groupId>
32+
<artifactId>jersey-bom</artifactId>
33+
<version>${jersey.version}</version>
34+
<type>pom</type>
35+
<scope>import</scope>
36+
</dependency>
37+
</dependencies>
38+
</dependencyManagement>
39+
40+
<dependencies>
41+
42+
<dependency>
43+
<groupId>org.glassfish.jersey.containers</groupId>
44+
<artifactId>jersey-container-grizzly2-http</artifactId>
45+
</dependency>
46+
47+
<dependency>
48+
<groupId>org.glassfish.jersey.inject</groupId>
49+
<artifactId>jersey-hk2</artifactId>
50+
<exclusions>
51+
<exclusion>
52+
<groupId>javax.inject</groupId>
53+
<artifactId>javax.inject</artifactId>
54+
</exclusion>
55+
</exclusions>
56+
</dependency>
57+
58+
<dependency>
59+
<groupId>junit</groupId>
60+
<artifactId>junit</artifactId>
61+
<version>${junit.version}</version>
62+
<scope>test</scope>
63+
</dependency>
64+
65+
</dependencies>
66+
67+
<build>
68+
<plugins>
69+
70+
<plugin>
71+
<groupId>org.apache.maven.plugins</groupId>
72+
<artifactId>maven-compiler-plugin</artifactId>
73+
<version>3.7.0</version>
74+
<configuration>
75+
<source>${java.version}</source>
76+
<target>${java.version}</target>
77+
</configuration>
78+
</plugin>
79+
80+
<plugin>
81+
<groupId>org.apache.maven.plugins</groupId>
82+
<artifactId>maven-shade-plugin</artifactId>
83+
<version>3.1.1</version>
84+
<configuration>
85+
<finalName>app</finalName>
86+
</configuration>
87+
<executions>
88+
<execution>
89+
<phase>package</phase>
90+
<goals>
91+
<goal>shade</goal>
92+
</goals>
93+
<configuration>
94+
<transformers>
95+
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
96+
<mainClass>com.miguno.App</mainClass>
97+
</transformer>
98+
</transformers>
99+
</configuration>
100+
</execution>
101+
</executions>
102+
</plugin>
103+
104+
</plugins>
105+
</build>
106+
107+
</project>

run_image.sh

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
declare -r IMAGE_NAME="miguno/java-docker-build"
4+
declare -r IMAGE_TAG="latest"
5+
declare -r APP_PORT="8123"
6+
7+
echo "Starting container for image '$IMAGE_NAME:$IMAGE_TAG', exposing port $APP_PORT/tcp"
8+
docker run -p $APP_PORT:$APP_PORT $IMAGE_NAME:$IMAGE_TAG
9+

src/main/java/com/miguno/App.java

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.miguno;
2+
3+
import org.glassfish.grizzly.http.server.HttpServer;
4+
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
5+
import org.glassfish.jersey.server.ResourceConfig;
6+
7+
import java.net.URI;
8+
9+
public class App {
10+
11+
protected static final String BASE_URI = "http://0.0.0.0:8123/";
12+
13+
/**
14+
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
15+
*/
16+
protected static HttpServer startServer() {
17+
// create a resource config that scans for JAX-RS resources and providers in com.miguno package
18+
final ResourceConfig rc = new ResourceConfig().packages("com.miguno");
19+
20+
// create and start a new instance of grizzly http server
21+
// exposing the Jersey application at BASE_URI
22+
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
23+
}
24+
25+
public static void main(String[] args) {
26+
startServer();
27+
System.out.println(String.format("Jersey app started with WADL available at %sapplication.wadl", BASE_URI));
28+
System.out.println(String.format("Endpoint is available at %sstatus", BASE_URI));
29+
}
30+
}
31+

src/main/java/com/miguno/Status.java

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.miguno;
2+
3+
import javax.ws.rs.GET;
4+
import javax.ws.rs.Path;
5+
import javax.ws.rs.Produces;
6+
import javax.ws.rs.core.MediaType;
7+
8+
@Path("status")
9+
public class Status {
10+
11+
@GET
12+
@Produces(MediaType.APPLICATION_JSON)
13+
public String statusInformation() {
14+
return "{\"status\": \"idle\"}\n";
15+
}
16+
}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.miguno;
2+
3+
import org.glassfish.grizzly.http.server.HttpServer;
4+
import org.junit.After;
5+
import org.junit.Before;
6+
import org.junit.Test;
7+
8+
import javax.ws.rs.client.Client;
9+
import javax.ws.rs.client.ClientBuilder;
10+
import javax.ws.rs.client.WebTarget;
11+
12+
import static org.junit.Assert.assertEquals;
13+
14+
public class StatusTest {
15+
16+
private HttpServer server;
17+
private WebTarget target;
18+
19+
@Before
20+
public void setUp() {
21+
server = App.startServer();
22+
Client c = ClientBuilder.newClient();
23+
target = c.target(App.BASE_URI);
24+
}
25+
26+
@After
27+
public void tearDown() {
28+
server.shutdownNow();
29+
}
30+
31+
@Test
32+
public void shouldReceiveIdleStatus() {
33+
String responseMsg = target.path("status").request().get(String.class);
34+
assertEquals("{\"status\": \"idle\"}\n", responseMsg);
35+
}
36+
}

0 commit comments

Comments
 (0)