---
# System prepended metadata

title: Spring Boot Docker
tags: [Tag(docker), Tag(Spring Boot)]

---

# 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/)
![Spring initializr](https://i.imgur.com/V1xnRAg.png)
如上圖，我選用Maven Project, Java Language, SpringBoot 2.5.6, Packaging Jar, Java 8, Dependencies: Spring Web後按Generate,就下載了檔案
![](https://i.imgur.com/SBCjhmh.png)
解開後，直接用IntellJ 新增專案的方式開啟這個目錄，選用Trust Project ，就自動下載相依套件。
依照第一課的做法就可以啟動服務, 接著實作第二課~第四課產生Restful API 實作的過程就不再贅述。
![](https://i.imgur.com/LJY5j1A.png)
透過postman確實驗證可以呼叫
ex: GET 
![](https://i.imgur.com/xvAQFGL.png)
ex: POST
![](https://i.imgur.com/5lCjGKn.png)

### 容器化

新增一個目錄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 如下
![](https://i.imgur.com/kPvGkXU.png)
透過Postman API可運作。

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

專案結構如下圖
![](https://i.imgur.com/KMoJwcs.png)


- 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時如下
![](https://i.imgur.com/H49JR2Y.png)


- Application版號修改時，有兩個地方記得改
    1. pom.xml
![](https://i.imgur.com/pe1Xh8S.png)


    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
```
![](https://i.imgur.com/oikzdTU.png)
啟動後使用postman測試API，確認work.