# Docker-ubuntu-建立BMI網站 ## 參考資料 :::info * 六角學院(YT) * [20 分鐘入門 Docker,建立屬於你自己的 Docker Image](https://youtu.be/RsY5cCc9RGM?si=z7axs0lkq7M4i_oe) * [超容易!10 分鐘透過 Docker hub 部署 image](https://youtu.be/hxX5MIohy1Q?si=Uh3NZ0uYfSX6Ih3h) * [從本地端上傳 Docker Image 至 Ubuntu 伺服器](https://youtu.be/JocSDHOFNzw?si=Az4c3Dmw040bTkBW) * [Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/) * [透過 Docker 快速建立及部署環境](https://rexhung0302.github.io/2021/12/10/20211210/) ::: ## Docker image的製作與應用 :::info * 請建立一個web server應用程式製作成docker image放置雲端網站(docker hub)。 * web應用程式計算BMI,輸入身高(cm)體重(kg),請費心設計UI,並且要符合RWD規範(可用前端工具bootstrap支援),並於該網頁顯示你的Hostname。 * docker image命名格式,==s1094845/web_dl_1094845:1==。確認image名字並可正常運作,將image完整名字貼到本作業區,老師依據你的image name下載驗證。 * 老師的驗證網站(ubuntu24.04伺服器版+docker)。 * 在Openstack的VM也啟動同樣版本docker container,並且截圖設定圖形連結(並註明網站網址),讓老師可以對照兩個版本。 ::: ## 實現方式 :::danger 實現前,需先準備 1. Dockerfile 2. index.html ::: ### ARM(自己電腦) 1. 下載 Docker Desktop ([Install Docker Desktop on Windows](https://docs.docker.com/desktop/install/windows-install/)) 2. 檢查 docker Image有哪些 `docker ps -a` 3. ==建立docker Image== `docker build -t web_dl_1094845:6 .` 4. ==執行docker Image== `docker run -d -p 8080:80 --name bmi_calculator web_dl_1094845:6` ![image](https://hackmd.io/_uploads/HyR1EpzHR.png) 5. 進入到 http://localhost:8080 看網頁 ![image](https://hackmd.io/_uploads/H1vgVpGrA.png) 6. ==失敗或是需要更新 Image前,先暫停再刪除== ``` docker stop bmi_calculator(Image ID/NAME) docker rm bmi_calculator(Image ID/NAME) ``` ### 建立AMD64(ubuntu虛擬機)的 Image #### 本地端處理 1. 下載 Docker Desktop ([Install Docker Desktop on Windows](https://docs.docker.com/desktop/install/windows-install/)) 2. ==建立docker Image== `docker build --platform=linux/amd64 -t s1094845/web_dl_1094845:6 .` 3. ==登入 docker hub== `docker login` 4. ==將 docker Image PUSH到docker hub== `docker push s1094845/web_dl_1094845:6` ![image](https://hackmd.io/_uploads/ByPb4azSR.png) 5. ==到 OpenStack 的管理安全性群組規則去新增 port規則== :::info Project(專案) -> Network(網路) -> 安全性群組 -> 管理規則 -> 加入規則 ::: ![image](https://hackmd.io/_uploads/BklGEBFHR.png) 6. :warning:由於新增 port規則,所以記得==要重啟虛擬機==:warning: #### Install Docker Engine on Ubuntu * Set up Docker's apt repository ``` sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc # Add the repository to Apt sources: echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update ``` * 安裝 `sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin` * 啟動 `sudo service docker start` * 測試 `sudo docker run hello-world ` #### ubuntu虛擬機執行 1. ==ssh 到ubuntu虛擬機== `ssh -i C:\Users\user\Downloads\key2.pem ubuntu@10.2.200.151` 2. ==pull(抓取) Image到 ubuntu虛擬機內== `sudo docker pull s1094845/web_dl_1094845:6` 3. ==執行 Image== `sudo docker run -e HOST_HOSTNAME=$(hostname) -p 8081:80 --name bmi_calculator_server s1094845/web_dl_1094845:6` 4. ==進入到 http://10.2.200.151:8081 看網頁== ![image](https://hackmd.io/_uploads/H1_3LcrI0.png) 5. 檢查 docker Image有哪些 `sudo docker ps -a` 6. ==失敗或是需要更新 Image前,先暫停再刪除== `sudo docker stop bmi_calculator_server` `sudo docker rm bmi_calculator_server` ## 程式碼 ### Dockerfile ```Dockerfile= # 使用官方 Python 运行时作为基础镜像 FROM python:3.8-slim # 设置工作目录为 /app WORKDIR /app # 将当前目录中的内容复制到 /app 中 COPY . . # 安装 Flask 及其它依赖 RUN pip install --no-cache-dir Flask # 在容器启动时运行 app.py CMD ["python", "app.py"] ``` ## app.py ``` from flask import Flask, jsonify, render_template_string import os import socket app = Flask(__name__) @app.route('/') def index(): html_content = ''' <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>BMI 計算器</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> <style> /* Add any custom CSS styles here */ </style> </head> <body> <div class="container mt-5"> <h1 class="mb-4">BMI Calculator</h1> <div id="hostname" class="mb-4">{{ hostname }}</div> <div class="form-group"> <label for="height">Height (cm):</label> <input type="number" id="height" class="form-control"> </div> <div class="form-group"> <label for="weight">Weight (kg):</label> <input type="number" id="weight" class="form-control"> </div> <button onclick="calculateBMI()" class="btn btn-primary">Calculate BMI</button> <div id="result" class="mt-3"></div> </div> <script> function calculateBMI() { var height = parseFloat(document.getElementById('height').value); var weight = parseFloat(document.getElementById('weight').value); var bmi = weight / ((height / 100) * (height / 100)); document.getElementById('result').innerHTML = "Your BMI is: " + bmi.toFixed(2); } function displayHostname() { document.getElementById('hostname').innerText = "{{ hostname }}"; } window.onload = function() { displayHostname(); } </script> </body> </html> ''' hostname = os.getenv('HOST_HOSTNAME', 'Unknown') return render_template_string(html_content, hostname=hostname) @app.route('/hostname') def get_hostname(): hostname = socket.gethostname() # 注意需要引入 socket 模块 return jsonify(hostname=hostname) if __name__ == '__main__': app.run(host='0.0.0.0', port=80) ``` ## 補充 ### .env 環境變數 ``` PORT=8080 ``` ### .dockerignore 不想被.docker打包的檔案放這邊 ``` .env ``` ### default.conf * 把 nginx的預設索引指向 index.html ```conf= server { listen 80; server_name localhost; # 設定預設索引檔為 index.html index index.html; location / { root /usr/share/nginx/html; # 不需要再指定 index.html,因為已經設定了預設索引文件 } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } ``` ### nginx.conf * nginx設定 ```conf= server{ listen 80 default_server; listen [::]:80 default_server; server_name lou.com; root /usr/share/nginx/html; index index.html; charset utf-8; access_log /var/log/nginx/access_log; error_log /var/log/nginx/error_log; } ```