Docker 教學 第 2 堂:Flask 容器、容器管理與 Volume
2-1 建立 Flask Web 容器(約 1 小時)
容器基本操作概念
現在我們要把映像檔「跑起來」,變成容器。最常用的指令是 docker run。
docker run 做了什麼?
- 檢查本機是否有指定的映像檔
- 如果沒有,自動從 Docker Hub 下載
- 用映像檔建立一個新的容器
- 啟動容器
實作:啟動一個 Python 容器
# 啟動一個 Python 容器,進入互動模式
docker run -it python:3.11 python參數說明:
-i(interactive):保持標準輸入開啟-t(tty):分配一個終端-it:這兩個通常一起用,讓你可以跟容器互動- 最後的
python:進入容器後要執行的指令
現在你已經在容器裡的 Python 互動環境了!試試看:
print("Hello from Docker!")
import sys
print(sys.version)按 Ctrl + D 或輸入 exit() 離開。
實作:用 Flask 建立一個 Web 應用容器
步驟 1:在本機建立專案資料夾
打開 PowerShell:
mkdir C:\docker-lab\flask-app
cd C:\docker-lab\flask-app步驟 2:建立 Flask 應用程式
用記事本或任何編輯器建立 app.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return '<h1>Hello Docker!</h1><p>This is running inside a container.</p>'
@app.route('/about')
def about():
return '<h1>About</h1><p>This is a Flask app running in Docker.</p>'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)步驟 3:建立 requirements.txt
flask步驟 4:啟動容器並執行 Flask
docker run -it -p 5000:5000 -v C:\docker-lab\flask-app:/app -w /app python:3.11 bash參數解釋(重點!):
-p 5000:5000:端口映射,把容器的 5000 port 映射到主機的 5000 port-v C:\docker-lab\flask-app:/app:掛載目錄,把本機的資料夾映射到容器裡的/app-w /app:設定工作目錄為/appbash:進入 bash shell
端口映射是初學者最容易搞混的地方。用比喻解釋:容器就像一棟大樓,裡面有很多房間(port),你需要在大樓外面立一個指標牌(映射),告訴外面的人要走哪個入口才能到達對的房間。
步驟 5:在容器裡安裝套件並啟動
pip install -r requirements.txt
python app.py步驟 6:測試
- 打開瀏覽器,前往
http://localhost:5000 - 你應該看到「Hello Docker!」
試著修改
app.py的回傳文字,然後重新啟動 Flask,體驗掛載目錄的方便——不需要重建容器就能更新程式碼。
2-2 容器管理指令大全(約 1 小時)
查看容器狀態
# 查看執行中的容器
docker ps
# 查看所有容器(包含已停止的)
docker ps -adocker ps 輸出範例:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9f89a41aca7d nginx "nginx -g..." 6 seconds ago Up 5 seconds 0.0.0.0:8080->80/tcp my-web各欄位說明:
| 欄位 | 說明 |
|---|---|
CONTAINER ID | 容器的唯一識別碼(就像身分證號) |
IMAGE | 建立容器所用的映像檔 |
COMMAND | 容器啟動時執行的命令(程式的入口點) |
CREATED | 容器建立的時間(多久前開的) |
STATUS | 目前狀態(Up 執行中、Exited 已停止、Restarting 重啟中…) |
PORTS | 容器對外映射的端口(0.0.0.0:8080->80 表示主機 8080 對應容器 80) |
NAMES | 容器的名字(方便人類記) |
停止、啟動與重新啟動
# 停止容器
docker stop <容器ID或名稱>
# 啟動已停止的容器
docker start <容器ID或名稱>
# 重新啟動容器(等於 stop + start)
docker restart <容器ID或名稱>
startvsrestart的差異:
docker start:只能啟動「已停止」的容器。對正在執行中的容器輸入docker start不會有任何效果。docker restart:不管容器是執行中還是已停止,都會重新啟動。什麼時候要用
restart? 實務上當容器的應用程式需要維護或更新設定、或是服務出問題(例如線程佔滿、記憶體洩漏)時,用docker restart可以快速重啟服務。
刪除容器
# 刪除容器(必須先停止才能刪)
docker rm <容器ID或名稱>
# 強制刪除執行中的容器(跳過停止步驟)
docker rm -f <容器ID或名稱>為什麼刪除容器之前需要先停止?
執行中的容器裡可能有程式正在處理資料(例如資料庫正在寫入)。如果直接刪除,可能會造成資料損壞或遺失。所以 Docker 預設要求你先
docker stop讓程式優雅地結束,再docker rm刪除。
docker rm -f則是強制刪除,不管容器在不在跑都直接砍。開發環境用很方便,但正式環境請盡量先 stop 再 rm。
查看 Log 與進入容器
# 查看容器的 log
docker logs <容器ID或名稱>
# 進入一個執行中的容器
docker exec -it <容器ID或名稱> bash什麼情況會用
docker exec?
情境 範例指令 Debug 除錯 — 程式出問題,進去看 log 檔或設定檔 docker exec -it my-app bash然後cat /app/error.log確認部署結果 — 檢查檔案有沒有正確複製、套件裝好了沒 docker exec -it my-app ls /app操作資料庫 — 直接進 MySQL 下 SQL 指令 docker exec -it my-mysql mysql -u root -p臨時測試 — 進去改個設定檔快速驗證想法 docker exec -it my-app bash然後修改檔案查看系統狀態 — 看記憶體、程序列表等 docker exec -it my-app top簡單來說:任何時候你需要「進去容器裡面看看」或「在容器裡跑一個指令」的時候,就用
docker exec。
幫容器取名字
docker run -d --name my-flask -p 5000:5000 -v C:\docker-lab\flask-app:/app -w /app python:3.11 bash -c "pip install flask && python app.py"新參數:
-d(detach):在背景執行--name my-flask:幫容器取一個好記的名字
用完即丟的容器:--rm
如果你只是想臨時進一個容器測試一下,用完就不需要了,可以加上 --rm:
# 有 --rm:exit 離開後容器自動消失,不留垃圾
docker run -it --rm ubuntu bash
# 沒有 --rm:停止後容器還在,要手動 docker rm 才會刪掉
docker run -it ubuntu bash沒有 --rm | 有 --rm | |
|---|---|---|
| 停止後容器還在嗎 | 在(docker ps -a 看得到) | 自動刪除 |
| 適合場景 | 長期跑的服務(Web、DB) | 臨時測試、試指令、看看就走 |
--rm可以避免忘記清理而累積一堆已停止的容器。養成好習慣:臨時用的容器都加--rm。
2-3 Volume 資料儲存(約 1 小時)
容器的資料會消失?
容器天生是「用完即丟」的設計。當你刪除一個容器時,裡面所有的檔案都會跟著消失。這在跑 Web 伺服器時沒問題(重建就好),但如果是資料庫,資料消失就完蛋了。
Volume 就是 Docker 用來解決這個問題的機制——把資料存在容器外面,容器刪掉了資料還在。
兩種掛載方式
Docker 的 -v 參數有兩種用法:
1. Bind Mount(綁定掛載):把主機的資料夾映射進容器
docker run -v "C:\my-project:/app" my-image- 左邊是主機路徑,右邊是容器路徑
- 主機和容器看到的是同一份檔案,改了會同步
- 適合開發環境:改程式碼不用重建容器
2. Named Volume(具名資料卷):讓 Docker 管理資料
docker run -v my-data:/var/lib/mysql mysql:8.0- 左邊是 Volume 名稱(不是路徑),右邊是容器路徑
- 資料存在 Docker 管理的位置,你不用管它放在哪
- 適合資料庫:安全、不會被意外修改
兩者的比較:
| Bind Mount | Named Volume | |
|---|---|---|
| 語法 | -v "C:\路徑:/容器路徑" | -v 名稱:/容器路徑 |
| 資料存在哪 | 你指定的主機路徑 | Docker 自動管理 |
| 適合場景 | 開發時同步程式碼 | 資料庫等需要持久化的資料 |
| 可攜性 | 差(路徑綁死在主機) | 好(跟著 Docker 走) |
Volume 管理指令
# 查看所有 Volume
docker volume ls
# 建立一個 Volume
docker volume create my-data
# 查看 Volume 詳情
docker volume inspect my-data
# 刪除 Volume
docker volume rm my-data
# 刪除所有沒在使用的 Volume
docker volume prune唯讀掛載
如果你只想讓容器讀取檔案、不允許修改,可以加上 :ro(read-only):
docker run -v "C:\my-config:/app/config:ro" my-image這在掛載設定檔時很實用,避免容器內的程式意外修改到你的檔案。
實作:親眼看到 Volume 的同步效果
來實際體驗「改宿主機的檔案,容器裡面馬上跟著變」:
步驟 1:建立測試資料夾和檔案
mkdir C:\docker-lab\volume-test在 C:\docker-lab\volume-test\ 下建立 index.html:
<h1>Hello Volume!</h1>
<p>這是第一個版本</p>步驟 2:啟動 Nginx 容器,掛載這個資料夾
docker run -d --name volume-demo -p 8080:80 -v "C:\docker-lab\volume-test:/usr/share/nginx/html" nginx步驟 3:確認網頁正常顯示
打開瀏覽器 http://localhost:8080,看到「Hello Volume! 這是第一個版本」。
步驟 4:進容器確認檔案
docker exec -it volume-demo shcat /usr/share/nginx/html/index.html
# 會看到跟宿主機一模一樣的內容
exit步驟 5:在宿主機修改檔案
用記事本打開 C:\docker-lab\volume-test\index.html,改成:
<h1>Hello Volume!</h1>
<p>這是修改後的第二個版本!</p>
<p>我在宿主機改的,容器裡面會自動同步</p>步驟 6:重新整理瀏覽器
直接按 F5 重新整理 http://localhost:8080,馬上看到新內容!不需要重啟容器、不需要重新 build。
步驟 7:反過來也行——在容器裡改,宿主機也會變
docker exec -it volume-demo sh# 在容器裡面新增一個檔案
echo "<h1>Created inside container!</h1>" > /usr/share/nginx/html/test.html
exit打開 http://localhost:8080/test.html,看到內容了。同時去宿主機的 C:\docker-lab\volume-test\ 看,test.html 也出現了!
步驟 8:清理
docker rm -f volume-demo重點整理:Bind Mount 就是宿主機和容器「共用同一份檔案」,改任何一邊另一邊都會馬上看到。這就是開發時用 Volume 的最大好處——改程式碼不用重建容器。