# Docker CI/CD ## 事先準備 * python(在 手動安裝、設定 使用) ```bash= # 裝 python $ sudo yum install -y python3 # 裝 pip $ wget https://bootstrap.pypa.io/pip/2.7/get-pip.py ``` ## 手動安裝、設定 * 建一個測試目錄 `mkdir -p iris` * 新增訓練模型 `train_model.py` ```python= # coding: utf-8 import pickle from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn import tree # simple demo for traing and saving model iris=datasets.load_iris() x=iris.data y=iris.target #labels for iris dataset labels ={ 0: "setosa", 1: "versicolor", 2: "virginica" } x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=.25) classifier=tree.DecisionTreeClassifier() classifier.fit(x_train,y_train) predictions=classifier.predict(x_test) #export the model model_name = 'model.pkl' print("finished training and dump the model as {0}".format(model_name)) pickle.dump(classifier, open(model_name,'wb')) ``` * 執行訓練模型 `$ python3 train_model.py` * 沒有套件就裝 `$ pip install sklearn` * 完成後 ```bash= $ python3 train_model.py finished training and dump the model as model.pkl $ ls get-pip.py model.pkl train_model.py ``` * 辨識模型的server `vim server.py` ```python= # coding: utf-8 import pickle from flask import Flask, request, jsonify app = Flask(__name__) # Load the model model = pickle.load(open('model.pkl', 'rb')) labels = { 0: "versicolor", 1: "setosa", 2: "virginica" } @app.route('/api', methods=['POST']) def predict(): # Get the data from the POST request. data = request.get_json(force = True) predict = model.predict(data['feature']) return jsonify(predict[0].tolist()) if __name__ == '__main__': app.run(debug = True, host = '0.0.0.0') ``` * 執行 server.py `$ python3 server.py` * 一樣缺套件就裝 `$ pip install flask` * 編輯客戶端(可再開一個終端或另一台機器) `$ vim client.py` ```python= # coding: utf-8 import requests # Change the value of experience that you want to test url = 'http://192.168.31.78:5000/api' # IP要改 feature = [[5.8, 4.0, 1.2, 0.2]] labels ={ 0: "setosa", 1: "versicolor", 2: "virginica" } r = requests.post(url,json={'feature': feature}) print(labels[r.json()]) ``` * 執行 ```bash= $ python3 client.py setosa ``` * 一樣缺套件就裝 `$ pip install requests` ## CI/CD * 目錄建立 ```bash= $ mkdir CICD $ cd CICD/ ``` * 檔案建立 ```bash= $ touch requirements.txt Dockerfile $ ls # train & server 跟前面是一樣的 Dockerfile requirements.txt server.py train_model.py ``` * requirements.txt ```bash= sklearn # 需要安裝的套件 flask requests ``` * Dockerfile ```dockerfile= FROM nitincypher/docker-ubuntu-python-pip # 有 python 的 image COPY ./requirements.txt /app/requirements.txt 把要安裝的套件檔案傳上去 WORKDIR /app RUN pip install -r requirements.txt # 安裝檔案內的套件 COPY server.py /app COPY train_model.py /app CMD python /app/train_model.py && python /app/server.py ``` * 建立 image `$ sudo docker build -t iris:1.0 .` * 執行 ```bash= $ sudo docker run -d --name iris -p 5000:5000 iris:1.0 876053f103532d9ab1654c1c23580873e0e57c79620ac7bed264acb1270c7471 ``` * 客戶端測試 ```bash= $ python3 client.py setosa ``` ![image](https://hackmd.io/_uploads/H1Q-ZLVH6.png) ### GitLab * 準備兩台VM (d1 d2) * 把 ssh pub 的 key 丟上 GitLab (兩台都要) ```= # cd .ssh # ls authorized_keys id_rsa id_rsa.pub known_hosts # cat id_rsa.pub 把 id_rsa.pub 複製到 GitLab ``` ![image](https://hackmd.io/_uploads/H1qVYUESp.png) **完成畫面** ![image](https://hackmd.io/_uploads/rkTjtUESp.png) **回到主頁建一個用來弄 iris 的 project** ![image](https://hackmd.io/_uploads/BJwZ5UErp.png) * VM1 (開發端) * git `$ sudo yum install git -y` ```bash= $ git config --global user.name "[Name]" $ git config --global user.email "[Email]" $ cd CICD/ # 進到要佈署的目錄 $ git init $ git remote add origin https://gitlab.com/xuan_lin1/test-iris.git $ git add. $ git commit -m "Initial commit(說明)" $ git push -u origin master ``` ![1701243519470](https://hackmd.io/_uploads/BJsc9w4S6.gif) * 上GitLab看上傳結果 ![image](https://hackmd.io/_uploads/rkpWjPVrT.png) * VM2 (運行端) * git 安裝 `$ sudo yum install git -y` * runner 安裝 `sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64` * 改變權限 `sudo chmod +x /usr/local/bin/gitlab-runner` * 新增使用者, 給他家目錄 `sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash` * 把 gitlab-runner 加到 docker 的群組, 這樣他也能使用 docker `sudo usermod -aG docker gitlab-runner` * gitlab-runner 設定 `/usr/local/bin/gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner` * gitlab-runner 啟動 `/usr/local/bin/gitlab-runner start` * 檢查 ![image](https://hackmd.io/_uploads/HkVYJVJfR.png) * 註冊 `gitlab-runner register` * 複製Token ![image](https://hackmd.io/_uploads/rJq4x4kGC.png) ![image](https://hackmd.io/_uploads/S1vtxVJMA.png) * 後續設定 ![image](https://hackmd.io/_uploads/SJPvG41zA.png) * 回gitlab 檢查 runner 狀態 ![螢幕擷取畫面 2024-05-01 110954](https://hackmd.io/_uploads/BJZ0zE1M0.png) * 再回到 VM1 1. 在配置目錄下新增 .gitlab-ci.yml ```yaml= stages: - deploy docker-deploy: stage: deploy script: - docker build -t iris . - if [ $(docker ps -aq --filter name=iris) ]; then docker rm -f iris; fi - docker run -d -p 5000:5000 --name iris tags: - d2 ``` 2. 上傳 ```bash= $ git add . $ git commit -m "yml commit" [master 886c767] yml commit 1 file changed, 11 insertions(+) create mode 100644 .gitlab-ci.yml $ git push -uf origin master . . . . . . . . . remote: To https://gitlab.com/xuan_lin1/iris2024.git 342f1b3..886c767 master -> master Branch master set up to track remote branch master from origin. ``` 3. 上傳檢查 ![image](https://hackmd.io/_uploads/S10O_VyGC.png) **可以在 jobs 查看執行過程** ![image](https://hackmd.io/_uploads/SJ21t4yzR.png) 4. 測試 (在非runner 的機器執行前面做過的 client.py) **client.py 的IP要設為runner IP** ![image](https://hackmd.io/_uploads/SyB7tNkzC.png)