前言
因為家人有個資料統計需求,不太碰後端的我臨時用了 python 寫了支簡單的爬蟲 + 資料處理;後來覺得既然都起了這個頭,那就順便再學一下用 flask 開發 api 吧;完成後想要部署到我的 server 上,又覺得那就再趁機學一下 Docker 吧(好幾年前有用 Docker 的 Laradock 建構論文用到的程式,但早已荒廢)。
我把 Docker 相關的步驟給筆記下來,給自己日後複習,有錯誤的地方也歡迎指教。以下介紹如何 build python docker image。
安裝 Docker
MacOS 用 brew 安裝,Ubuntu 用 apt-get 安裝:
# MacOS
$ brew update
$ brew cask install docker
# Ubuntu
$ sudo apt-get update
$ sudo apt-get install docker.io
安裝完成後,使用 groups
指令查看目前 user 是否有 docker group 權限:
$ groups
<your_user_name>
若沒有出現 docker,請輸入以下指令,避免每次都要打 sudo 才能執行 docker 指令:
$ sudo usermod -G docker -a <your_user_name>
執行完上述指令後,請重新登出後再次查看是否有出現 docker:
$ groups
<your_user_name> docker
有出現 docker 代表成功,可以試著使用 docker version
指令查看目前版本,來確保 docker 指令運行正常:
$ docker version
將程式打包成 Docker Image
假設我要打包的是 test_api.py
這支 python 檔,我會先在 local 創建一個資料夾叫 test-docker
,並在底下建立這些檔案:
test-docker
app
test_api.py # 欲打包的檔案
Dockerfile # 先建立空檔案,等等撰寫內容
特別注意,python 檔要設定成 host 0.0.0.0 才可以被外部訪問,所以在 test_api.py 的 app.run() 加上如下參數:
if __name__ == '__main__':
app.run(host='0.0.0.0')
接著要將本機的 python 環境列成清單,以讓 Dockerfile 可以依照這份清單建立 Image 的環境:
$ pip freeze > requirements.txt
這樣我們的 test-docker 資料夾底下就會有 requirements.txt 的檔案了。
test-docker
app
test_api.py
Dockerfile
requirements.txt
接下來要撰寫 Dockerfile,內容如下:
# Basic Image Environment
# 使用 slim 版本減輕 Image 容量
FROM python:3.9-slim
# 指定 Image 中的工作目錄
WORKDIR /code
# 將 Dockerfile 所在目錄下的所有檔案複製到 Image 的工作目錄 /code 底下
ADD . /code
# 在 Image 中執行的指令:安裝 requirements.txt 中所指定的 dependencies
RUN pip install -r requirements.txt
# Container 啟動指令:Container 啟動後通過 python 運行 test_api.py
CMD ["python", "./app/test_api.py"]
python3.9 | python3.9-slim | python3.9-alpine |
---|---|---|
842MB | 118MB | 55.8MB |
這樣子打包的東西都準備好了,可以準備下一步驟。
建構 Docker Image
在 Dockerfile 所在目錄下執行:
$ docker build -t test-api:v1 .
-t 參數指定 Image 的名字(若沒有指定版號 :v1 則會變成 :latest)。除此之外,需特別注意指令最後還有一個 .
。. 表示當前目錄,這裡指的是 Dockerfile 所在的目錄。
查看已建構好的 Docker Image 清單
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
test-api v1 5e3bbceaf52a 2 minutes ago 452MB
執行 Docker Container
$ docker run -p <port> test-api:v1
接下來只要看到服務有正常運行就代表成功囉!
以下順便介紹如何刪除 Image 和 Container。
刪除 Image
首先需透過上面講過的 docker image ls
來找到欲刪除的 Image 的 ID,接著放入 docker rmi
指令中。
# 一次刪除一張
$ docker rmi <your_image_id>
# 一次刪除多張
$ docker rmi <your_image_id> <your_image_id> ...
若有其他 Container 正在使用欲刪除的 Image,則會出現以下錯誤:
Error response from daemon: conflict: unable to delete <image_id> (must be forced) - image is being used by stopped container <container_id>
刪除 Container
可以透過上面錯誤訊息提到的 container_id 直接刪除,也可以使用 docker ps -a
來查看現有 Container。
有了 Container ID 後即可下停用及刪除指令:
$ docker stop <container_id>
$ docker rm <container_id>
參考資料