# 雲端技術實務期末 :::info **無法使用到學校電腦,使用ubuntu22.04 desktop進行測試** 參考資料 https://hackmd.io/@saID5sq_QhCsFgtxP02KkA/rJBkb3pU3 https://ithelp.ithome.com.tw/articles/10191016 https://ithelp.ithome.com.tw/articles/10191139 https://hackmd.io/@A9aTZ-55SDW754ufW1ctXw/HyAmVctPh ::: :::danger **評語:** 1. 主機的hostname不是學號?? 2. dokcer pull出現Warning?? **解決方法:** 1. 直接抓hostname會抓到container的id ,解決方式只查到可以用sudo docker run -e HOSTNAME=$(hostname) -p 8080:8080 {image_name:tag} 2. 可能是run flask 出現Warning,https://blog.csdn.net/qq_42991509/article/details/127101393 ::: ## 1.安裝Docker :::info https://www.51cto.com/article/715086.html https://hackmd.io/@whYPD8MBSHWRZV6y-ymFwQ/rynv0a7CT ::: ## 2.安裝web server ```cmd sudo apt-get -y update sudo apt-get -y install nginx ``` > 輸入虛擬機IP查看網站是否有正確運作 ![image](https://hackmd.io/_uploads/B1EWS6cSC.png) ## 3.建立一個web server應用程式製作成docker image放置雲端網站(docker hub) ### 建立DockerFile > 建立寫 Dockerfile 會用到的資料夾(docker-test),指令如下 ```cmd mkdir docker-test cd docker-test ``` > 撰寫Dockerfile ``` vi Dockerfile ``` :::success Dockerfile 的內容如下 ``` # 使用官方的 Python 執行環境作為基本的 Docker 影像 FROM python:3.9-slim # 設置工作目錄 WORKDIR /app # 複製當前目錄下的所有文件到工作目錄 COPY . . # 安裝 requirements.txt 中所列的必要套件 RUN pip install -r requirements.txt # 讓 80 連接埠可以從 Docker 容器外部存取 EXPOSE 80 # 當 Docker 容器啟動時,自動執行 app.py CMD ["python", "app.py"] ``` ::: > 在相同的目錄中創建名為 app.py 及 requirements.txt 的文件 :::info Dockerfile 需要用到另外兩個檔案,分別為requirements.txt 與 app.py,app.py 就是我們自己撰寫的 Python 應用程式,而 requirements.txt 則是相依套件的列表。 > 創建一個Flask應用程式。 app.py ```python= from flask import Flask, render_template import socket import os app = Flask(__name__) @app.route('/') def index(): # 獲取主機名 hostname = socket.gethostname() VM_hostname = os.getenv('HOSTNAME') return render_template('index.html', hostname=hostname, VM_hostname=VM_hostname) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=8080) ``` > 在 requirements.txt 寫入所需套件 requirements.txt ```tex= Flask ``` > **在docker-test/templates目錄內,創建index.html文件,內容如下:** ``` mkdir templates cd templates ``` > index.html ```htmlmixed= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>1092960 BMI計算器</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> <style> @media screen and (min-width: 600px) { table { width: 80%; } } </style> </head> <body> <script> function calculateBMI() { var flag = true; const weight = document.getElementById('weight').value; const height = document.getElementById('height').value; //還原起始顏色 restoreColor(); if (isNaN(Number(weight,10))) { alert("您輸入的體重格式錯誤"); flag = false; }else if (weight === null || weight.trim() === '') { alert("請輸入您的體重"); flag = false; } if (isNaN(Number(height,10))) { alert("您輸入的身高格式錯誤"); flag = false; }else if (height === null || height.trim() === '') { alert("請輸入您的身高"); flag = false; } if (weight && height && flag) { const heightInMeters = height / 100; const bmi = weight / (heightInMeters * heightInMeters); const bmiRounded = bmi.toFixed(2); if (bmiRounded < 18.5) { changeColor('underweight'); }else if (bmiRounded < 24) { changeColor('normal'); }else { changeColor('overweight'); } document.getElementById('result').innerText = `你的 BMI 值為 ${bmiRounded}`; } else { document.getElementById('result').innerText = `你的 BMI 值為 ???`; } } function changeColor(weightRange){ var allHighlight = document.getElementsByClassName(weightRange); for (var i=0;i<allHighlight.length;i++){ allHighlight[i].style.backgroundColor = '#FFFF6F'; } } function restoreColor(){ var allHighlight = document.getElementsByClassName('ori'); for (var i=0;i<allHighlight.length;i++){ allHighlight[i].style.backgroundColor = '#FFFFFF'; } } document.addEventListener('DOMContentLoaded', function() { var vmHostname = document.getElementById('VM_hostname'); var vmHint = document.getElementById('VM_hint'); if (vmHostname.innerText !== 'VM_Hostname not available') { vmHint.style.display = 'none'; }else { vmHostname.style.display = 'none'; } }); </script> <div align="center"> <h1>1092960 BMI計算器</h1> <h3 id="hostname">你的hostname為 {{ hostname }}</h3> {% if VM_hostname != hostname %} <h4 id="VM_hostname">{{ VM_ostname }}</h4> {% else %} <h4 id="VM_hostname">VM_Hostname not available</h4> {% endif %} <div id="VM_hint">若是想取得VM的hostname,而非container請輸入<br>sudo docker run -e HOSTNAME=$(hostname) -p 8080:8080 {image_name:tag}</div> <div> <span>身高:</span> <input id="height" type="text" size="11" placeholder="請輸入身高" style="border: 1px solid #0B6060; text-align:right;"> <font face="Arial"> cm</font> </div> <br> <div> <span>體重:</span> <input id="weight" type="text" size="11" placeholder="請輸入體重" style="border: 1px solid #0B6060; text-align:right;"> <font face="Arial"> kg</font><font color="#FFFFFF">.</font> </div> <br> <button onclick="calculateBMI()">計算 BMI</button> <div id="result">你的 BMI 值為 ???</div> <br> <table align="center" border="1" cellspacing="0" bordercolordark="black" bordercolorlight="black" height="159"> <tbody> <tr bordercolor="#cccccc" bgcolor="#66B3FF"> <td width="100" height="35"></td> <td width="190" height="35"> <div align="center"><font color="#000000"><span>身體質量指數(BMI)<br>(kg/m²)</span><br></font></div> </td> <td width="150" height="35"> <div align="center"><font color="#000000"><span>腰圍<br>(cm)</span><br></font></div> </td> </tr> <tr bordercolor="#ACD6FF"> <td width="100" bgcolor="#C4E1FF"> <div align="center">體重過輕</div> </td> <td width="180" class="underweight ori"> <div align="center">BMI < 18.5</div> </td> <td width="150" class="underweight ori"> <p align="center">---</p> </td> </tr> <tr bordercolor="#cccccc"> <td width="100" bgcolor="#C4E1FF"> <div align="center">正常範圍</div> </td> <td width="180" class="normal ori"> <div align="center">18.5 ≤ BMI < 24</div> </td> <td width="150" class="normal ori"> <p align="center">---</p> </td> </tr> <tr bordercolor="#cccccc"> <td width="100" bgcolor="#C4E1FF"> <div align="center">異常範圍</div> </td> <td valign="top" width="180" class="overweight ori"> <div align="center"> <span>過重:24 ≤ BMI < 27<br>輕度肥胖:27 ≤ BMI < 30<br>中度肥胖:30 ≤ BMI < 35<br>重度肥胖:BMI ≥ 35</span> </div> </td> <td valign="top" width="150" class="overweight ori"> <div align="center"> <p>男性: ≥ 90公分<br>女性: ≥ 80公分<br></p> </div> </td> </tr> </tbody> </table> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> </body> ``` ::: :::success 資料夾的結構如下圖: flask_app/ ├── app.py ├── Dockerfile ├── requirements.txt ├── templates/ │ └── index.html ![image](https://hackmd.io/_uploads/H14DFT5S0.png) ::: ### 建立Docker image > **返回到包含Dockerfile的目錄中**,運行以下命令來建置Docker image ``` docker build -t s1092960 --network=host . ``` :::warning 如果出現**permission denied**最簡單就是改成 ``` sudo docker build -t s1092960 --network=host . sudo docker images ``` ::: ![image](https://hackmd.io/_uploads/B1BoY69H0.png) > Build 完 Docker Image 之後,使用 docker images 指令查看是否有 build 成功 ``` docker images ``` ![image](https://hackmd.io/_uploads/H1Hrq6qHR.png) ### 執行 Docker Container :::info docker run -p 8080:8080 {image_name:tag} 輸入http://localhost:8080查看網頁 若是使用伺服器請輸入http://{ip}:8080 ::: ```cmd docker run -p 8080:8080 s1092960:version3 ``` ![image](https://hackmd.io/_uploads/r1E2hC9BR.png) ![image](https://hackmd.io/_uploads/SJ5R20qSA.png) :::success 若是想取得VM的hostname,而非container請輸入 ``` sudo docker run -e HOSTNAME=$(hostname) -p 8080:8080 {image_name:tag} ``` ![image](https://hackmd.io/_uploads/BJK7a0cS0.png) ![image](https://hackmd.io/_uploads/H1wEpR5BC.png) ::: ## 4.最終打包,把 Docker Image Push 到 Docker Hub 上 :::success > 到dockerhub註冊帳號 https://hub.docker.com/ > 確認執行沒問題後建立Docker image並將其命名為web_dl_1092960 ``` docker build -t web_dl_1092960 --network=host . ``` ![image](https://hackmd.io/_uploads/H1IBy1oBA.png) ::: ### 1. 打開 terminal 輸入 docker images,畫面如下 ![image](https://hackmd.io/_uploads/HyONbJiHC.png) ### 2. 要把 Docker Image Push 到 Docker Hub 上,需要把 Docker Image 加上 tag,如下指令 :::info > 使用 docker tag 命令為本地的 Docker image打上標籤。 使用的Docker tag格式如下: docker tag < Image ID or Image Name > < DockerHub帳號 >/< Image Name >:< Tag > ::: ``` docker tag web_dl_1092960 whitefir473/web_dl_1092960:0001 ``` ![image](https://hackmd.io/_uploads/rJiBf1jrC.png) ### 3. 輸入 docker login 指令登入到 Docker Hub,畫面如下 ``` docker login ``` ![image](https://hackmd.io/_uploads/rJSO71orC.png) ### 4.使用 docker push 指令把 Docker Image Push 到 Docker Hub 裡,指令如下 ``` docker push whitefir473/web_dl_1092960:0001 ``` ![image](https://hackmd.io/_uploads/HJl1LLyirR.png) ![image](https://hackmd.io/_uploads/BkWu8yjSC.png) ## 5.測試是否成功的把 Docker Image Push 到 Docker Hub 上 :::success 使用另一台機器或將 local 的 Image 刪除掉 ::: ### 1. 在 Docker Hub 網站裡,登入帳號進去可以看到 Repositories 已經有 whitefir473/web_dl_1092960 的 Docker Image ![image](https://hackmd.io/_uploads/BkWu8yjSC.png) ### 2. 使用 docker rm 指令把 local 的 Image 刪除掉,測試從 Docker Hub pull Docker Image 下來,指令如下 ``` docker rmi -f whitefir473/web_dl_1092960:0001 docker rmi -f web_dl_1092960 ``` ![image](https://hackmd.io/_uploads/S12CkloHC.png) ### 3. 從 Docker Hub Pull Docker Image 下來,指令如下 ``` docker pull whitefir473/web_dl_1092960:0001 ``` ![image](https://hackmd.io/_uploads/B1R2xeiBC.png) ### 4. 啟動 Docker Container,指令如下 ```cmd docker run -p 8080:8080 whitefir473/web_dl_1092960:0001 ``` ![image](https://hackmd.io/_uploads/rkb1ZxoHA.png) :::success > 若是想取得VM的hostname,而非container請輸入 > sudo docker run -e HOSTNAME=$(hostname) -p 8080:8080 {image_name:tag} ``` sudo docker run -e HOSTNAME=$(hostname) -p 8080:8080 whitefir473/web_dl_1092960:0001 ``` ![image](https://hackmd.io/_uploads/ByW7-xsH0.png) ::: ### 5. 啟動完成之後就可以使用 Browser 查看結果,輸入 URL 位址為 http://localhost:8080 可以看到如下畫面 :::info 輸入http://localhost:8080查看網頁 若是使用伺服器請輸入http://{ip}:8080 ::: ![image](https://hackmd.io/_uploads/rySW-xiSA.png) ![image](https://hackmd.io/_uploads/SJtVbgsS0.png) ## 6.OpenStack的VM也啟動 ![image](https://hackmd.io/_uploads/rkM0CGaB0.png) ![image](https://hackmd.io/_uploads/SyWEJmaH0.png) ![image](https://hackmd.io/_uploads/ByinZQTSR.png) ![image](https://hackmd.io/_uploads/rkirMQTrR.png) ![image](https://hackmd.io/_uploads/By8A7QpHC.png) ![image](https://hackmd.io/_uploads/SJgW4XTSA.png)