# 1091雲端_第18組_雲端應用 CI/CD
###### tags: `雲端運算` `CI/CD` `EC2` `Drone` `Docker`
---
<div style="text-align:center">
<b>
<p>本筆記僅提供國立臺灣科技大學1091學年度</p>
<p>【MI3510701】雲端運算應用與實務課程之使用</p>
<p>請勿外流,若有侵權,法律必究。</p>
<p>Creater</p>
<p>臺灣科技大學 四資管三</p>
<p>B10709005 張宜楨</p>
<p>B10709032 陳靖宜</p>
<p>B10709034 王慧婷</p>
<p>B10709036 洪薏璇</p>
</b>
</div>
---
## 目錄
[ToC]
---
# Step0. 環境建置
* 一台堪用PC
* 申請AWS 帳號 [教育帳號申請]()
* 你習慣的IDE軟體
---
# Step1. 建立EC2
## 1-1 建立實例 Create instance
1. AWS登入後,點選 **`EC2`**

2. 點選 **`instance launch new instance`**

3. 搜尋 **`ubuntu`** 並下載最新版本
這邊我們下載的是 **20.04** 這個版本

4. 選擇 **`Free trail`**
不選的話會付錢喔,小心錢包XD

5. 點button: **` review and launch -> launch`**

6. 接著視窗會跳出訊息,並要你 **`建立Key Pair`**
1. 將Choose an exsiting key par改為**Create a new key pair**
2. 輸入你要的Key pair name
3. *`Download Key Pair`*
Key pair是為了讓你可以在電腦上與ubuntu連線的金鑰

7. **`Download Key Pair`**
將Key儲存你要的位置,之後的步驟會用到
※建議儲存在C://User/使用者名稱/.ssh 避免下一步驟PC偵測不到Key

8. 完成後就點選 **`Launch Instances`**
這邊會設定一下下,等他跑完
9. **`View Instances`**
恭喜你完成25%了,那下面步驟請參照[1-2_本地連上instance](#1-2_本地連上instance)
## 1-2 本地連上instance
1. 可以看到**剛剛建立的instance** 然後點擊 **`執行個體ID超連結`**
Name預設為空白,這邊我們為了方便辨識,把它改名為 drone test

2. 會看到以下畫面,然後點 **`連線/Connect`**

3. 你會看到其ip位置以及name,**我們把他記下**
建議記在一個筆記本內

4. **下載MobaXterm**
[下載教學: IT好用軟體– MobaXterm(遠端Terminal連線軟體)](https://it001.pixnet.net/blog/post/350223902-it%E5%A5%BD%E7%94%A8%E8%BB%9F%E9%AB%94%E2%80%93-mobaxterm%28%E9%81%A0%E7%AB%AFterminal%E9%80%A3%E7%B7%9A%E8%BB%9F%E9%AB%94%29)
通常網路教學是使用putty,但是MobaXterm比較新也好用,還可以省下記一些cmd指令的時間,User Friendly至上XD

5. **打開MobaXterm**,點擊 **`Session`** -> **`SSH`**

6. 輸入SSH 設定的東西
在Basic SSH Setting -> 輸入ip和name
在Advance SSH Setting -> **`Use private key`** 選擇剛剛下載的key pair檔案(*.pem)

7. 上一步驟輸入完畢點選Button: **OK**
等待一下,看到這個畫面代表你連線成功囉

8. Moboxterm可以顯示這個虛擬機的資料夾很user friendly

---
# Step2. 在EC2 Instance建置Docker
## 2-1 在ubuntu上下載docker
Reference: https://docs.docker.com/engine/install/ubuntu/
1. 卸載舊版本 docer.io package
```java=
// Uninstall old versions
$ sudo apt-get remove docker docker-engine docker.io containerd runc
```
跑出這個代表之前沒有裝過docker,所以沒有解安裝,屬正常情況

2. 重整/初始化repository
這邊的動作有點像是網頁F5,讓系統重新讀取資料內容
```java=
// install using the repository
$ sudo apt-get update
```
3. 安裝剛剛的package
中間可能會問你幾次問題,是關於授權的,輸入Y就好了!
反斜線是linux語法的cmd 換行
```java=
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
```
==**注意!** 只要有反斜線一定要注意,**前面有空格,後面沒有空格**==
4. 在ubontu下載Docker
Curl是一個在Linux上用來透過 HTTP Protocol下載和上傳檔案的指令。它基本的指令格式為 curl [options] [URL...]
```java=
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```
5. 在ubontu確認金鑰的可信度
```java=
// Verify that you now have the key with the fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88, by searching for the last 8 characters of the fingerprint.
$ sudo apt-key fingerprint 0EBFCD88
```
6. 加入stable repository
```java=
// Use the following command to set up the stable repository. To add the nightly or test repository, add the word nightly or test (or both) after the word stable in the commands below. Learn about nightly and test channels.
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
```
7. 再重整repository
```java=
//INSTALL DOCKER ENGINE
$ sudo apt-get update
```
8. 安裝Docker
```java=
//輸入Y就好了
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```
9. 查看docker版本
```java=
$ sudo docker -v
```
10. 跑跑看docker image有沒有問題
```java=
$ sudo docker run hello-world
```
看到這行就代表Docker安裝成功了~

## 2-2 在ubuntu上建立docker group
### Manage Docker as a non-root user
> 賦予docker擁有更高的系統權限
> 這樣就不需要執行docker的指令都要加上sudo
> Reference:
>- [[Docker] 使用非 root 權限來執行 docker client](https://ephrain.net/docker-%E4%BD%BF%E7%94%A8%E9%9D%9E-root-%E6%AC%8A%E9%99%90%E4%BE%86%E5%9F%B7%E8%A1%8C-docker-client/)
>- [Post-installation steps for Linux](https://docs.docker.com/engine/install/linux-postinstall/)
1. 建立一group叫做docker
```java=
$ sudo groupadd docker
```
2. 將目前的使用者加入到docker group裡面
```java=
$ sudo usermod -aG docker $USER
```
3. 輸入此指令並重新登入
加入群組後,假設這個帳號就是登入中的帳號的話,group 的資訊並不會立刻更新,因此Log out and log back in so that your group membership is re-evaluated.
```java=
$ newgrp docker
```
### Configure Docker to start on boot
> 設定虛擬機一開機就開啟docker service
> 此後不必額外再啟動Docker
> Most current Linux distributions (RHEL, CentOS, Fedora, Ubuntu 16.04 and higher) use **`systemd`** to manage which services start when the system boots. Ubuntu 14.10 and below use upstart.
1. 下次重新開機,需要能自動啟動 docker service
```java=
$ sudo systemctl enable docker
```
2. 重新啟動docker,整入設定
```java=
$ sudo systemctl restart docker
```
---
# Step3. 安裝Drone前準備的資料
## 3-1 先去Github設定OAuth
首先登入個人GitHub Page
1. 從右上選單進到 **`settings`**

2. 在左邊選項選擇 **`Developer settings`** 裡面的 **`OAuth Apps-> New OAuth App`**

3. 輸w入 Github App Name, homepage url, callback url
* Github App name看你喜歡叫甚麼
* homepage url請輸入aws ec2提供的Public DNS

* 可以在這裡看到public DNS

4. 產生Client Secrets,並記下
==**注意!這個Secrets只產生一次,之後就會遮蔽起來不讓使用者看到,所以一定要記下來**==

5. 建立記事本把client id 和 client secrets記下來

6. 去AWS找到你的public dns

7. 產生Docker image之間溝通的高強度加密識別碼
**去ubuntu command line輸入以下指令**
``` java=
$ openssl rand -hex 16
```
ubuntu會回傳給你一串數字,請在記事本裡記下,這個密碼會確保兩端間的通信是安全的。
> 到目前為止記事本內容大概會長這樣
> 
## 3-2 啟動Drone的image 和 Drone Runner image
1. 請把剛剛記事本的五筆資料放到下面的欄位把Docker drone跑起來(記得空格規則!)
```
docker run \
--volume=/var/lib/drone:/data \
--env=DRONE_GITHUB_CLIENT_ID={1. GitHub裡面的Client ID} \
--env=DRONE_GITHUB_CLIENT_SECRET={2. Github裡面的Client secret} \
--env=DRONE_RPC_SECRET={3. 請透過openssl產生隨機的字串為了跟runner溝通} \
--env=DRONE_SERVER_HOST={4. 不用放http只要放ec2-....的public DNS部分} \
--env=DRONE_SERVER_PROTO=http \
--env=DRONE_USER_CREATE=username:{5. Github的帳號名稱},admin:true \ 要加上不然對github沒有權限 並且也無法使用docker.soke
--publish=80:80 \
--publish=443:443 \
--restart=always \
--detach=true \
--name=drone \
drone/drone:1
```
2. 再來把docker runner 跑起來
```
docker run -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DRONE_RPC_PROTO=http \
-e DRONE_RPC_HOST={EC2的public dns} \
-e DRONE_RPC_SECRET={openssl 產生的字串 要跟docker drone一樣} \
-e DRONE_RUNNER_CAPACITY=3 \
-e DRONE_RUNNER_NAME=${HOSTNAME} \
-p 3000:3000 \
--restart always \
--name runner \
drone/drone-runner-docker:1
```
3. 檢查docker images是否有再跑
```java=
// find container name = drone/drone-runner-docker:1 的id是甚麼
docker ps
```
```java=
// 查看那個container的log
docker logs {輸入剛剛看到的containerid}
```
> 
> 看到successfully就ok了
---
# Step4. 開始執行CI/CD!
## 4-1 AWS連結github
==先去security group把port打開(非常重要!!)==
1. 去security groups 點edit

2. 打開這些port

3. 回到執行個體打開url,並登入你的github
==要把https改成http==

4. 尋找你fork到你的repository的project

5. 設定trust and save

## 4-2 設定CI/CD
1. 找一個你要測試的網頁包
也可以參考[使用 GitHub 免費製作個人網站](https://gitbook.tw/chapters/github/using-github-pages.html)

2. 確定這個網頁包可以執行
3. 在此專案下新增一 **`Dockerfle`** 檔案
```dockerfile=
# pull official base image 13.12.0-alpine
FROM node:13.12.0-alpine
# set working directory container 裡面的工作目錄
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# install app dependencies
COPY package.json ./
RUN yarn install --silent
# add app
COPY . ./
# start app
CMD ["yarn", "start"]
```
4. 新增一 **```.drone.yml```** 檔案
```yaml=
kind: pipeline
type: docker
name: Staging
steps:
- name: build
image: node
commands:
- yarn install
- name: test
image: node
commands:
- yarn test
- name: Build docker image
image: docker/compose:1.23.2
volumes:
- name: docker_socket
path: /var/run/docker.sock
commands:
- echo "test"
- cd /drone/src/
- docker build -t dinogame:latest .
- name: Create service
image: docker/compose
volumes:
- name: docker_socket
path: /var/run/docker.sock
commands:
#把原本的container 關掉
- docker-compose -f /drone/src/docker-compose.yml -p backend down
#重新開啟現在的container
- docker-compose -f /drone/src/docker-compose.yml -p backend up -d
volumes:
- name: docker_socket
host:
path: /var/run/docker.sock
```
5. 新增一 **```docker-compose.yml```** 檔案
```yaml=
version: '3.3'
# 定義您想要在應用程式中執行的服務 (或container) 清單
services:
dronetesthere:
image: dinogame
build: .
ports:
- '3001:3001'
```
6. 傳至github
## 4-3 執行CI/CD
嘗試修改網站內容並再次push至github,此時會發現repository旁邊有黃色的齒輪轉動,表示偵測到更新

點進後,會發現Drone開始根據drone.yml開始進行CI/CD


更新完成後,將頁面的網址改為dns地址:port,就可以看到更新後的網站了

{"metaMigratedAt":"2023-06-15T18:10:34.679Z","metaMigratedFrom":"Content","title":"1091雲端_第18組_雲端應用 CI/CD","breaks":true,"contributors":"[{\"id\":\"82557649-458c-4d70-a112-b29ba13e7ff3\",\"add\":3243,\"del\":1327},{\"id\":\"af5884d9-772f-44ab-9071-79ea08eb9f73\",\"add\":7,\"del\":0},{\"id\":\"fbf5d567-be55-4b18-8d5f-e5b3bb952dab\",\"add\":9221,\"del\":1276}]"}