├── .gitignore
├── Dockerfile
├── README.md
├── docker
├── pom.xml
├── screenshots
└── 00_docker_test.PNG
└── src
├── main
└── java
│ └── com
│ └── levo
│ └── dockerexample
│ ├── DockerApp.java
│ └── controller
│ └── HelloController.java
└── test
└── java
└── com
└── levo
└── dockerexample
└── PlaceHolderForTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | target
3 | .classpath
4 | .project
5 | .settings
6 | src/main/webapp/META-INF
7 | .idea
8 | *.iml
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use an official OpenJDK runtime as a parent image
2 | FROM openjdk:8-jre-alpine
3 |
4 | # set shell to bash
5 | # source: https://stackoverflow.com/a/40944512/3128926
6 | RUN apk update && apk add bash
7 |
8 | # Set the working directory to /app
9 | WORKDIR /app
10 |
11 | # Copy the fat jar into the container at /app
12 | COPY /target/docker-java-app-example.jar /app
13 |
14 | # Make port 8080 available to the world outside this container
15 | EXPOSE 8080
16 |
17 | # Run jar file when the container launches
18 | CMD ["java", "-jar", "docker-java-app-example.jar"]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Docker Container With Spring Boot Web Service Example
2 | =====================================================
3 | The aim is to demonstrate a running docker container with a spring boot standalone
4 | web service thus, I've written the web service with Spring Boot as simple. For intensive
5 | a complete web service example with Spring Boot, you can check out my other repository
6 | which is [spring-boot-restful-web-service-example
7 | ](https://github.com/bzdgn/spring-boot-restful-web-service-example).
8 |
9 | TOC
10 | ---
11 | - [0 Spring Boot Web Service](#0-spring-boot-web-service)
12 | - [1 Dockerfile](#1-dockerfile)
13 | - [2 Building The Image](#2-building-the-image)
14 | - [3 Running And Testing The Docker Container](#3-running-and-testing-the-docker-container)
15 | - [4 Getting Inside The Docker Container](#4-getting-inside-the-docker-container)
16 | - [5 Stopping The Docker Container](#5-stopping-the-docker-container)
17 | - [6 Cheat Sheet](#6-cheat-sheet)
18 |
19 | 0 Spring Boot Web Service
20 | -------------------------
21 | The web service we are using in this example is kept as simple as possible for the simplicity
22 | of demonstrating how to run a docker container. It has a simple controller class which is quite
23 | straight-forward as it is obvious: [HelloController](https://github.com/bzdgn/docker-spring-boot-java-web-service-example/blob/master/src/main/java/com/levo/dockerexample/controller/HelloController.java)
24 |
25 | The key thing using a standalone Spring Boot application is to create a **Fat Jar**, also known as
26 | **Uber Jar**. In order to create the **Uber Jar**, there are two things to be done;
27 |
28 | 1. Add an **start-class** to point to the class acting as the Entry Point as the example below.
29 | The reason we are doing so is, we need to reference the **.jar** file in the [Dockerfile](https://github.com/bzdgn/docker-spring-boot-java-web-service-example/blob/master/Dockerfile);
30 |
31 | ```
32 |
33 | com.levo.dockerexample.DockerApp
34 |
35 | ```
36 |
37 | In our example, you will see the properties as below in the [pom.xml](https://github.com/bzdgn/docker-spring-boot-java-web-service-example/blob/master/pom.xml) file.
38 |
39 | ```
40 |
41 | UTF-8
42 | UTF-8
43 | 1.8
44 | com.levo.dockerexample.DockerApp
45 |
46 | ```
47 |
48 | 2. The second thing is, we need to know the name of our **Fat Jar** (a.k.a. **Uber Jar**). In order
49 | to do that, we use define the **final name** under **build** section of our [pom.xml](https://github.com/bzdgn/docker-spring-boot-java-web-service-example/blob/master/pom.xml) file as below;
50 |
51 | ```
52 |
53 | docker-java-app-example
54 | ...
55 | ...
56 |
57 | ```
58 |
59 | In our example, the build section is as below;
60 |
61 | ```
62 |
63 | docker-java-app-example
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-maven-plugin
68 |
69 |
70 |
71 | ```
72 |
73 | As we create our **Fat Jar** (a.k.a. **Uber Jar**) and we define the final name of our jar,
74 | we are all set and we can write the [Dockerfile](https://github.com/bzdgn/docker-spring-boot-java-web-service-example/blob/master/Dockerfile).
75 |
76 | [Go back to TOC](#toc)
77 |
78 |
79 | 1 Dockerfile
80 | ------------
81 | With the **Dockerfile** we can define, configure and initialize our image and container. In **Dockerfile** we can define;
82 |
83 | 1. Which image we are going to use. We need a docker image that has the OpenJDK and thus we are going to use Alpine;
84 |
85 | ```
86 | FROM openjdk:8-jre-alpine
87 | ```
88 |
89 | 2. Which shell we are going to have. I prefer **Bash** which I find easy to use;
90 |
91 | ```
92 | RUN apk update && apk add bash
93 | ```
94 |
95 | 3. The working directory our app is going to run. The name of the working directory will be **app**;
96 |
97 | ```
98 | WORKDIR /app
99 | ```
100 |
101 | 4. The files we need to copy into our image. We will need only the **Uber Jar** file so let's copy it into the working dir;
102 |
103 | ```
104 | COPY /target/docker-java-app-example.jar /app
105 | ```
106 |
107 | 5. The port number(s) that we need to expose to reach out from the container. Spring Boot default port is 8080;
108 |
109 | ```
110 | EXPOSE 8080
111 | ```
112 |
113 | 6. The commands that we need to run as the container goes live. And we need to add simply "java -jar .jar" format;
114 |
115 | ```
116 | CMD ["java", "-jar", "docker-java-app-example.jar"]
117 | ```
118 |
119 | Notify that the CMD(command) parameters are separated with comma.
120 |
121 | Then our **Dockerfile** will be as below;
122 |
123 | ```
124 | # Use an official OpenJDK runtime as a parent image
125 | FROM openjdk:8-jre-alpine
126 |
127 | # set shell to bash
128 | # source: https://stackoverflow.com/a/40944512/3128926
129 | RUN apk update && apk add bash
130 |
131 | # Set the working directory to /app
132 | WORKDIR /app
133 |
134 | # Copy the fat jar into the container at /app
135 | COPY /target/docker-java-app-example.jar /app
136 |
137 | # Make port 8080 available to the world outside this container
138 | EXPOSE 8080
139 |
140 | # Run jar file when the container launches
141 | CMD ["java", "-jar", "docker-java-app-example.jar"]
142 | ```
143 |
144 | Now our [Dockerfile](https://github.com/bzdgn/docker-spring-boot-java-web-service-example/blob/master/Dockerfile) is all set, we can directly build the image.
145 |
146 | [Go back to TOC](#toc)
147 |
148 |
149 | 2 Building The Image
150 | --------------------
151 | Before building the image, we need to create the **Uber Jar** (aka **Fat Jar**) file, to do so, just clean install with maven as below;
152 |
153 | ```
154 | mvn clean install
155 | ```
156 |
157 | Now our **Uber Jar** file is created under the target folder with the format: "target/.jar" (or .war based on package in .pom file)
158 |
159 | To build the image, we will use **docker build** command and tag it. The last parameter will be the directory, by using dot ("."),
160 | we point to the current directory. So you must run this command on the top level directory of this repository.
161 |
162 | ```
163 | docker build --tag=docker-java-hello-world-app .
164 | ```
165 |
166 | As you run the command which is written above, a successful example output will be as below;
167 |
168 | ```
169 | C:\00_ANA\JavaEE\WS\docker-java-app-example>docker build --tag=docker-java-hello-world-app .
170 | Sending build context to Docker daemon 16.85MB
171 | Step 1/6 : FROM openjdk:8-jre-alpine
172 | ---> 7e72a7dcf7dc
173 | Step 2/6 : RUN apk update && apk add bash
174 | ---> Running in 66ebd9812836
175 | fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
176 | fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
177 | v3.8.2-21-g54952ee375 [http://dl-cdn.alpinelinux.org/alpine/v3.8/main]
178 | v3.8.2-21-g54952ee375 [http://dl-cdn.alpinelinux.org/alpine/v3.8/community]
179 | OK: 9546 distinct packages available
180 | (1/5) Installing ncurses-terminfo-base (6.1_p20180818-r1)
181 | (2/5) Installing ncurses-terminfo (6.1_p20180818-r1)
182 | (3/5) Installing ncurses-libs (6.1_p20180818-r1)
183 | (4/5) Installing readline (7.0.003-r0)
184 | (5/5) Installing bash (4.4.19-r1)
185 | Executing bash-4.4.19-r1.post-install
186 | Executing busybox-1.28.4-r2.trigger
187 | OK: 91 MiB in 57 packages
188 | Removing intermediate container 66ebd9812836
189 | ---> fa54653163af
190 | Step 3/6 : WORKDIR /app
191 | ---> Running in c94cbad8627a
192 | Removing intermediate container c94cbad8627a
193 | ---> 5a58ac387fe7
194 | Step 4/6 : COPY /target/docker-java-app-example.jar /app
195 | ---> aa5930ee4a75
196 | Step 5/6 : EXPOSE 8080
197 | ---> Running in 851b519d4514
198 | Removing intermediate container 851b519d4514
199 | ---> 210ed5d1dc3f
200 | Step 6/6 : CMD ["java", "-jar", "docker-java-app-example.jar"]
201 | ---> Running in 55b84275e095
202 | Removing intermediate container 55b84275e095
203 | ---> a0c355a25236
204 | Successfully built a0c355a25236
205 | Successfully tagged docker-java-hello-world-app:latest
206 | SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
207 | ```
208 |
209 | After the image is built, you can check it with the ```docker image ls``` command. An example is as below;
210 |
211 | ```
212 | C:\00_ANA\JavaEE\WS\docker-java-app-example>docker image ls
213 | REPOSITORY TAG IMAGE ID CREATED SIZE
214 | docker-java-hello-world-app latest a0c355a25236 About a minute ago 105MB
215 | openjdk 8-jre-alpine 7e72a7dcf7dc 5 days ago 83.1MB
216 | ```
217 |
218 |
219 | [Go back to TOC](#toc)
220 |
221 |
222 | 3 Running And Testing The Docker Container
223 | ------------------------------------------
224 | Now we have our docker image ready however, we need to run a container based on our image. We can simply run our docker container
225 | as below;
226 |
227 | ```
228 | docker run -p 80:8080 docker-java-hello-world-app
229 | ```
230 |
231 | The format is simple;
232 |
233 | ```
234 | docker run -p :
235 | ```
236 |
237 | The parameter **p** stands for the **port**. **External port** is the port that will be available outside of the docker container.
238 | The **internal port** is the port that will be available inside the docker container, which is **8080** because the default port of
239 | Spring Boot is set to **8080**. So outside of the Docker Container, we will use the port number **80**, and it is mapped to **8080**
240 | and will reach to the Spring Boot application.
241 |
242 | As you run the command, you can open up your browser, you can go to this url [http://localhost:80/docker-java-app/test](http://localhost/docker-java-app/test)
243 |
244 | Then you will see the container is returning the string message with date as below;
245 |
246 |
247 |
248 |
249 |
250 | [Go back to TOC](#toc)
251 |
252 |
253 | 4 Getting Inside The Docker Container
254 | -------------------------------------
255 | While our container is running, we can get inside the running container for different purposes like checking out the logging, configuration
256 | and other stuff. Before getting inside the container, we need to know the **container id** of our container. To do so, let's first list
257 | the running containers with the following command;
258 |
259 | ```
260 | docker container ls
261 | ```
262 |
263 | A successful output example is as below;
264 |
265 | ```
266 | C:\00_ANA\JavaEE\WS\docker-java-app-example>docker container ls
267 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
268 | 159c3ee8ef39 docker-java-hello-world-app "java -jar docker-ja…" 7 minutes ago Up 7 minutes 0.0.0.0:80->8080/tcp adoring_jackson
269 | ```
270 |
271 | You can see the container id on the left-most part of the output. For this example, the container id is "159c3ee8ef39". Each container will
272 | have a different hash, so when you run it, it will be different. We are going to use this container id to get into the docker container as below;
273 |
274 | ```
275 | docker exec -it /bin/bash
276 | ```
277 |
278 | The "/bin/bash" at the end denotes that we are going to use **bash** shell, which our image has.
279 |
280 | A successful output is as below;
281 |
282 | ```
283 | C:\00_ANA\JavaEE\WS\docker-java-app-example>docker exec -it 159c3ee8ef39 /bin/bash
284 | bash-4.4# pwd
285 | /app
286 | bash-4.4# ls
287 | docker-java-app-example.jar
288 | bash-4.4# ps -ef
289 | PID USER TIME COMMAND
290 | 1 root 0:08 java -jar docker-java-app-example.jar
291 | 45 root 0:00 /bin/bash
292 | 53 root 0:00 ps -ef
293 | bash-4.4# exit
294 | exit
295 |
296 | C:\00_ANA\JavaEE\WS\docker-java-app-example>
297 | ```
298 |
299 | As you can see, the commands "pwd", "ls" and "ps -ef" successfully ran. We can see that our jar file stand in the "app" folder
300 | as we have configured in our Dockerfile. We can easily exit with the "exit" command.
301 |
302 | [Go back to TOC](#toc)
303 |
304 |
305 | 5 Stopping The Docker Container
306 | -------------------------------
307 | To stop the docker container, we are going to use this command;
308 |
309 | ```
310 | docker stop
311 | ```
312 |
313 | It is as simple as that. Remember that when we ran the docker container, we have the Spring Boot output. I'm using windows while
314 | writing this repository and if you hit ctrl+c, even if you are out of the scope of the logging output of Spring Boot, the container
315 | is still alive. To stop it, you have to use the command above. A successful example is as below;
316 |
317 | ```
318 | C:\00_ANA\JavaEE\WS\docker-java-app-example>docker container ls
319 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
320 | 159c3ee8ef39 docker-java-hello-world-app "java -jar docker-ja…" 16 minutes ago Up 16 minutes 0.0.0.0:80->8080/tcp adoring_jackson
321 |
322 | C:\00_ANA\JavaEE\WS\docker-java-app-example>docker container stop 159c3ee8ef39
323 | 159c3ee8ef39
324 |
325 | C:\00_ANA\JavaEE\WS\docker-java-app-example>docker container ls
326 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
327 |
328 | C:\00_ANA\JavaEE\WS\docker-java-app-example>
329 | ```
330 |
331 | [Go back to TOC](#toc)
332 |
333 |
334 | 6 Cheat Sheet
335 | -------------
336 |
337 |
338 | 1. Maven install to create the fat jar
339 |
340 | ```
341 | mvn clean install
342 | ```
343 |
344 | 2. Docker build
345 |
346 | ```
347 | docker build --tag=docker-java-hello-world-app .
348 | ```
349 |
350 | 3. Docker run
351 |
352 | ```
353 | docker run -p 80:8080 docker-java-hello-world-app
354 | ```
355 |
356 | 4. Test the app
357 |
358 | ```
359 | http://localhost/docker-java-app/test
360 | ```
361 |
362 | 5. Get the container id
363 |
364 | ```
365 | docker container ls
366 | ```
367 |
368 | 6. Get into the app
369 |
370 | ```
371 | docker exec -it /bin/bash
372 | ```
373 |
374 | 7. To stop the container
375 |
376 | ```
377 | docker container stop
378 | ```
379 |
380 |
381 | [Go back to TOC](#toc)
--------------------------------------------------------------------------------
/docker:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jaiswaladi246/docker-spring-boot-java-web-service-example/bc62e9956921403cc92fe655e0de06c735a9f90a/docker
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.levo.dockerexample
5 | docker-java-app-example
6 | jar
7 | 1.0-SNAPSHOT
8 | docker-java-app-example
9 | http://maven.apache.org
10 |
11 |
12 | UTF-8
13 | UTF-8
14 | 1.8
15 | com.levo.dockerexample.DockerApp
16 |
17 |
18 |
19 | org.springframework.boot
20 | spring-boot-starter-parent
21 | 2.1.1.RELEASE
22 |
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 |
31 |
32 | docker-java-app-example
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-maven-plugin
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/screenshots/00_docker_test.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jaiswaladi246/docker-spring-boot-java-web-service-example/bc62e9956921403cc92fe655e0de06c735a9f90a/screenshots/00_docker_test.PNG
--------------------------------------------------------------------------------
/src/main/java/com/levo/dockerexample/DockerApp.java:
--------------------------------------------------------------------------------
1 | package com.levo.dockerexample;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class DockerApp {
8 | public static void main(String[] args) {
9 | SpringApplication.run(DockerApp.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/levo/dockerexample/controller/HelloController.java:
--------------------------------------------------------------------------------
1 | package com.levo.dockerexample.controller;
2 |
3 | import java.util.Date;
4 |
5 | import org.springframework.web.bind.annotation.RequestMapping;
6 | import org.springframework.web.bind.annotation.RequestMethod;
7 | import org.springframework.web.bind.annotation.RestController;
8 |
9 | @RestController
10 | @RequestMapping("docker-java-app")
11 | public class HelloController {
12 |
13 | @RequestMapping(value = "/test", method = RequestMethod.GET)
14 | public String test() {
15 | return "docker-java-app is up and running: " + new Date();
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/java/com/levo/dockerexample/PlaceHolderForTest.java:
--------------------------------------------------------------------------------
1 | package com.levo.dockerexample;
2 |
3 | public class PlaceHolderForTest {
4 |
5 | }
6 |
--------------------------------------------------------------------------------