Docker 教學 第 2 堂:Flask 容器、容器管理與 Volume

2-1 建立 Flask Web 容器(約 1 小時)

容器基本操作概念

現在我們要把映像檔「跑起來」,變成容器。最常用的指令是 docker run

docker run 做了什麼?

  1. 檢查本機是否有指定的映像檔
  2. 如果沒有,自動從 Docker Hub 下載
  3. 用映像檔建立一個新的容器
  4. 啟動容器

實作:啟動一個 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:設定工作目錄為 /app
  • bash:進入 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 -a

docker 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或名稱>

start vs restart 的差異:

  • 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 MountNamed 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 sh
cat /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 的最大好處——改程式碼不用重建容器。

0%