在前幾天的教學中,我們學會了 Docker 的基本使用。然而,你可能已經注意到一個問題,那就是當 Container 重新啟動時,所有資料都會消失。
如果在 Container 中有一些必須保存的資料,該怎麼辦呢?Docker 已經考慮到這一點,解決方案就是使用 Volume。雖然 Volume 不是三個主要組件之一,但它是非常重要的,尤其是當重要資料不能丟失時。
首先,讓我們回到之前的專案結構:
test-project
├── app.py
├── Dockerfile
└── requirements.txt
接下來,我們將修改 Dockerfile,請注意以下更改:
FROM python:3.9.10-alpine3.15
WORKDIR /test-project
# 注意:只複製 requirements.txt 進去
COPY requirements.txt .
RUN pip install -r requirements.txt
# 注意:新增 VOLUME 指令,設定可以掛載的位置
VOLUME /test-project
EXPOSE 5000
# 注意:拆分 CMD 為 ENTRYPOINT 與 CMD 兩行
ENTRYPOINT ["python"]
CMD ["app.py"]
接著重新建立 Image:
$ docker build --no-cache -t flask-env .
現在,我們直接運行剛才建立的 Image,但這次的指令稍有不同:
$ docker run -it -p 5000:5000 -v <你本機/test-project的路徑>:/test-project flask-env
然後,你可以在 http://localhost:5000 看到相同的內容。
如果不太理解剛才的操作,沒問題,我們來逐步解釋做了什麼。
首先,Dockerfile 第三行由 COPY * .
改成了 COPY requirements.txt .
。這是因為我們不想複製其他東西進入 Image,只需複製 requirements.txt 進去安裝相應的環境即可。
接著,第五行新增了 VOLUME /test-project
,這行主要設定了 Image 中可以掛載的位置。在運行時,我們使用了 -v <你本機/test-project的路徑>:/test-project
,這樣可以將整個 test-project 目錄掛載進去。因此,在運行之後,我們可以執行 python app.py 的指令。
第七行把原本的 CMD ["python", "app.py"]
拆成了兩行,即 ENTRYPOINT ["python"]
與 CMD ["app.py"]
。這樣做的原因是,我們的環境已安裝相關套件,但沒有將程式放進 Image(對 Image 來說)。假如我們想運行不同檔名的程式,只需簡單地在指令中添加參數,就像下方的指令一樣:
# 假設想運行的是 main.py
docker run -it -p 5000:5000 -v <你本機/test-project的路徑>:/test-project flask-env main.py
這樣就可以再次使用相同的 Image,而不需要重新打包 Image,雖然都是使用相同的套件,卻能執行不同的程式。
同理,如果 Container 向掛載的目錄儲存檔案,也可以在本機掛載的目錄找到檔案。