[軟體概念入門系列][Workshop] Linux與後端服務 #2
前置準備
- 依據官網文件安裝docker並可以成功執行hello-world container
sudo docker run hello-world
若在wsl中起docker service遇到問題可參考此篇
2. 在 https://hub.docker.com/ 用公司信箱註冊自己的帳號
Workshop目標
將上次我們建立的python flask API, nginx改為使用docker建立
你會學習到
- 如何撰寫docker file並透過docker build建立python image
- 如何用同樣的docker image建立多個container
- 如何對執行中的container進行操作及變更
建立python flask api docker image
- 建立稍後要放進docker image中的python檔
用vim建立app.py並填入以下程式碼
import socket
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "this message comes from " + socket.gethostname()
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=5566)
這個python script會建立一個回傳server name的API
執行以下指令讓api啟動
python3 -m venv .venv
source .venv/bin/activate
python app.py
接著瀏覽 http://localhost:5566/ 確認API正常運行即可以中斷python執行
2. 建立python API docker file
在app.py的同一個目錄下, 用vim建立dockerfile
FROM python:3.9
WORKDIR /app
RUN pip install Flask
COPY app.py /app/
CMD ["python", "app.py"]
3. 建立docker image
執行以下指令, 以剛剛撰寫的dockerfile來建立docker image, 並將image命名為flask-api, 版號為1.0
docker build -t flask-api:1.0 .
接著執行以下指令確認docker image已經存在於本機
docker image ls
4. 將docker image執行為docker container
docker run --rm -p 3000:5566 --name my-api-1 flask-api:1.0
瀏覽 http://localhost:3000/ 確認 API 可被存取到
接著再開另一個cmd/powershell/windows terminal tab進入wsl
並執行以下指令確認執行中的container資訊
docker ps -a
docker inspect my-api-1
docker stats my-api-1
docker logs my-api-1
確認完回到container執行的畫面, 按下ctrl+c結束container執行
並改執行以下指定讓container在背景執行
docker run --rm -p 3000:5566 --name my-api-1 -d flask-api:1.0
執行第二個使用5000 port的api
docker run --rm -p 5000:5566 --name my-api-2 -d flask-api:1.0
瀏覽 http://localhost:3000/ 與 http://localhost:5000/ 確認兩個container都正常執行
5. 將 docker image 推上 docker hub
在 docker hub上建立一個叫做flask-api的repository
https://hub.docker.com/repository/create
接著將剛剛建立的flask-api docker image重新tag為你的docker hub namespace下的docker image
使用docker login登入docker hub並將image推上docker hub
docker tag flask-api:1.0 {dockerhub_namespace}/flask-api:1.0
docker login
docker push {dockerhub_namespace}/flask-api:1.0
重新整理你的docker hub repository, 應可以看到image被成功推上去了
建立nginx container並設定config
- 停止原有wsl中的nginx
執行以下指令停止workshop #1安裝的nginx
sudo service nginx stop
sudo service nginx status
這時候瀏覽 http://workshop-load-balance.com/ 應會無法存取
2. 啟用nginx container
執行以下指令使用官方的nginx image, 並把原本nginx config的folder設定成volumn指定到container內
docker run --name my-nginx -v /etc/nginx/:/etc/nginx/ -p 80:80 -d nginx
這時候瀏覽 http://workshop-load-balance.com/ 應該會是502 Bad Gateway
因為nginx找不到upstream的python flask api, 因此要改成正確的python flask api才能正確地存取到
3. 調整nginx config將相關的ip改為my-api-1及my-api-2的container ip
先用以下指令查詢兩個container的ip
docker inspect my-api-1 | grep IPAddress
docker inspect my-api-2 | grep IPAddress
將nginx config改為以下
upstream loadbalance_backend {
server {my-api-1的IP}:5566;
server {my-api-2的IP}:5566;
}
server {
listen 80;
server_name workshop-load-balance.com;
location / {
proxy_pass http://loadbalance_backend/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
接著執行以下指令讓nginx container reload config
docker exec my-nginx nginx -s reload
現在瀏覽 http://workshop-load-balance.com/
應可以正常做到load balance存取到兩個python flask api了
使用docker compose一次管理多個container
- 停止所有的container
docker ps
docker stop {$container name 1} {$container name 2} {$container name 3}
2. 撰寫docker compose yaml
使用vim用以下內容建立docker-compose.yaml
version: '3'
services:
nginx:
image: nginx:latest
container_name: my-nginx
ports:
- "80:80"
volumes:
- /etc/nginx/:/etc/nginx/
api-1:
image: flask-api:1.0
container_name: my-api-1
ports:
- "3000:5566"
api-2:
image: flask-api:1.0
container_name: my-api-2
ports:
- "5000:5566"
3. 使用docker compose建立多個container
執行以下指令以docker-compose.yaml的內容建立多個container
docker compose -f docker-compose.yaml up
# 如果想要背景執行則用下面這個
docker compose -f docker-compose.yaml up -d
# 停止則要使用
docker compose -f docker-compose.yaml down
4. 查詢my-api-1及my-api-2的IP並調整nginx config
同前面操作過的步驟, 查詢目前兩個container的IP並更新到nginx config
docker inspect my-api-1 | grep IPAddress
docker inspect my-api-2 | grep IPAddress
#調整nginx config後reload
docker exec my-nginx nginx -s reload
瀏覽 http://workshop-load-balance.com/ 檢查結果是否如預期
Recap
回顧我們這次做過的內容
- 撰寫docker file, 使用python官方base image再加上自行開發的python api file建立新的docker file
- 將docker image執行為container, 並可以執行多個不同的container, 使用相關指令查看container的設定及執行狀況
- 將docker image推上docker hub讓別人可以使用
- 使用docker volumn從container外部編輯nginx config, 並使用docker exec讓container執行nginx reload指令
- 使用docker compose一次管理多個container
延伸思考
- 同樣的image要上到不同環境執行成container時通常會連到不同環境的資料庫或其他共用資源, 要怎麼樣做比較方便控制?
- 如果要管理大量container的執行及停止, 是否有更簡便的方式?
- 如果container有異常或效能不足時, 是否有機制可以繼續維持服務正常?
- 每次調整container造成IP變動的時候, 都必須要去查詢並更新nginx config, 是否有更簡便的方式?