# Spring Boot Docker
###### tags: `Tag(docker)` `Tag(Spring Boot)`
### 前文
這是一篇練習心得筆記
本來用tomcat+war檔包成docker([該篇筆記](https://hackmd.io/@CqRN13XlTXynDVuQ6clCkw/rydHC81Ot)),但同事說應該是用Spring Boot,所以找了相關資源,主要參考Vincent Zheng的系列文章,作者寫的內容讓我容易理解,超感恩~
- [【Spring Boot】第1課-從建立專案到啟動程式](https://chikuwa-tech-study.blogspot.com/2021/05/spring-boot-create-project.html)
- [【Spring Boot】第2課-認識 RESTful API 的設計方式](https://chikuwa-tech-study.blogspot.com/2021/05/spring-boot-restful-api.html)
- [【Spring Boot】第3課-在 Controller 實作 API(一)](https://chikuwa-tech-study.blogspot.com/2021/05/spring-boot-controller-1.html)
- [【Spring Boot】第4課-在 Controller 實作 API(二)](https://chikuwa-tech-study.blogspot.com/2021/05/spring-boot-controller-2.html)
成功做出用IntellJ 產生Spring Boot 專案,並用postman測試 Restful API。就以這樣的服務,開始容器化。
### 服務
必須強力稱讚, Spring initializr 是好物 [https://start.spring.io/](https://start.spring.io/)

如上圖,我選用Maven Project, Java Language, SpringBoot 2.5.6, Packaging Jar, Java 8, Dependencies: Spring Web後按Generate,就下載了檔案

解開後,直接用IntellJ 新增專案的方式開啟這個目錄,選用Trust Project ,就自動下載相依套件。
依照第一課的做法就可以啟動服務, 接著實作第二課~第四課產生Restful API 實作的過程就不再贅述。

透過postman確實驗證可以呼叫
ex: GET

ex: POST

### 容器化
新增一個目錄springdocker
```
springdocker
├── Dockerfile
├── docker-compose.yml
└── helloSpring-0.0.1-SNAPSHOT.jar
```
- Dockerfile
```
From openjdk:8-jdk-alpine
Label springboot_app_image:1
COPY helloSpring-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
EXPOSE 8080
```
- docker-compose.yml
```
version: '3.7'
services:
web:
container_name: springboot_app
build: .
image: springboot_app_image
ports:
- 8080:8080
```
- helloSpring-0.0.1-SNAPSHOT.jar
將Spring專案目錄下Target/helloSpring-0.0.1-SNAPSHOT.jar 複製到此。
建立 image 並啟動 container
```
docker-compose up -d
```
Docker Dashboard 啟動的 container 如下

透過Postman API可運作。
### 優化在IntellJ 包裝docker image 並定義版號
雖然IntelJ有plug-in Docker, 但我覺得沒有必要,IntellJ已經結合terminal容易下命令。
在專案目錄下新增springdocker
並在該目錄下放置Dockerfile 與 docker-compose.yml,
增加一個 rundockerbuild.sh
專案結構如下圖

- Dockerfile
```
FROM openjdk:8-jdk-alpine
COPY helloSpring-*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
EXPOSE 8080
```
- docker-compose.yml
```
version: '3.7'
services:
web:
# build: .
# image: dancyu/springboot_app_image
image: 192.168.64.6:5000/dancyu/springboot_app_image
ports:
- 8080:8080
```
- rundockerbuild.sh
```
version=1.0.5-`date '+%Y%m%d%H%M'`
echo $version
rm -rf app.jar
cp ../target/helloSpring-*.jar .
docker build \
-t dancyu/springboot_app_image:${version} \
-t dancyu/springboot_app_image:latest \
-t 192.168.64.6:5000/dancyu/springboot_app_image:latest \
-t 192.168.64.6:5000/dancyu/springboot_app_image:${version} .
docker push 192.168.64.6:5000/dancyu/springboot_app_image:${version}
docker push 192.168.64.6:5000/dancyu/springboot_app_image:latest```
```
說明:因為在本機有swarm實作,定義private registry server在192.168.64.6:5000([可參考這篇](https://hackmd.io/@dancyu/BJNAUOdOY)),因此build時直接加上一組private registry tag,並利用shell在產生鏡像之後,直接push到private registry
執行時rundockerbuild.sh時如下

- Application版號修改時,有兩個地方記得改
1. pom.xml

2. rundockerbuild.sh 的version
---
## 部署在swarm上
把1.0.5版在管理節點上執行前先調整docker-compose.yml
```
version: '3.7'
services:
web:
# build: .
# image: dancyu/springboot_app_image
image: 192.168.64.6:5000/dancyu/springboot_app_image:1.0.5
ports:
- 8080:8080
```
預設都是latest,看不出更版效果
部署指令:
```
sudo docker stack deploy --compose-file docker-compose.yml springdocker
```

啟動後使用postman測試API,確認work.