├── .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 | docker-web-test 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 | --------------------------------------------------------------------------------