資料庫持久化

如果您還沒發現的話,每次啟動容器時,您的待辦事項列表都是空的。為什麼會這樣?在本部分中,您將深入了解容器的運作方式。

容器的檔案系統

當容器運行時,它使用來自映像檔的各種層作為其檔案系統。每個容器還擁有自己的「暫存空間」來建立、更新或移除檔案。即使多個容器使用相同的映像檔,在一個容器中所做的任何變更,另一個容器也無法看見。

實踐操作

為了驗證這一點,您將啟動兩個容器。在第一個容器中,您會建立一個檔案。在第二個容器中,您會檢查該檔案是否存在。

  1. 啟動一個 Alpine 容器並在其中建立一個新檔案。

    $ docker run --rm alpine touch greeting.txt
    
    提示

    您在映像檔名稱(此處為 alpine)之後指定的任何指令,都會在容器內部執行。在本例中,指令 touch greeting.txt 會在容器的檔案系統中建立一個名為 greeting.txt 的檔案。

  2. 運行一個新的 Alpine 容器,並使用 stat 指令檢查該檔案是否存在。

    $ docker run --rm alpine stat greeting.txt
    

    您應該會看到類似以下的輸出,表明該檔案在新容器中不存在。

    stat: can't stat 'greeting.txt': No such file or directory
    

第一個容器建立的 greeting.txt 檔案在第二個容器中並不存在。這是因為每個容器的「頂層可寫層」是隔離的。儘管兩個容器共享組成基礎映像檔的相同底層層,但可寫層對於每個容器而言是獨一無二的。

容器儲存卷 (Volumes)

透過上述實驗,您可以看到每個容器每次啟動時都是從映像檔定義開始的。雖然容器可以建立、更新和刪除檔案,但當您移除容器時,這些變更就會丟失,且 Docker 會將所有變更隔離在該容器內。有了儲存卷 (Volumes),您可以改變這一切。

儲存卷 (Volumes) 提供了將容器的特定檔案系統路徑連接到主機的功能。如果您掛載容器中的目錄,該目錄中的變更也會顯現在主機上。如果您在容器重啟後掛載同一個目錄,您將會看到相同的檔案。

主要有兩種儲存卷類型。您最終會用到這兩種類型,但我們將從儲存卷掛載 (volume mounts) 開始。

待辦事項資料持久化

預設情況下,待辦事項應用程式會將其資料儲存在容器檔案系統中 /etc/todos/todo.db 的 SQLite 資料庫中。如果您不熟悉 SQLite,別擔心!它只是一個將所有資料儲存在單一檔案中的關聯式資料庫。雖然這對於大型應用程式來說不是最佳選擇,但對於小型演示來說已經足夠。您稍後將學習如何切換到其他資料庫引擎。

由於資料庫是單一檔案,如果您能將該檔案持久化在主機上並使其對下一個容器可用,它就應該能從上一個容器結束的地方繼續運作。透過建立一個儲存卷並將其附加(通常稱為「掛載」)到儲存資料的目錄,您就可以實現資料持久化。當您的容器寫入 todo.db 檔案時,資料將會持久化到主機的儲存卷中。

如前所述,您將使用儲存卷掛載。將儲存卷掛載想像成一個不透明的資料桶。Docker 完全管理該儲存卷,包括磁碟上的儲存位置。您只需要記住儲存卷的名稱即可。

建立儲存卷並啟動容器

您可以透過 CLI 或 Docker Desktop 的圖形介面來建立儲存卷並啟動容器。

  1. 使用 docker volume create 指令建立一個儲存卷。

    $ docker volume create todo-db
    
  2. 再次停止並移除待辦事項應用程式容器(使用 docker rm -f <id>),因為它目前在沒有使用持久化儲存卷的情況下運行。

  3. 啟動待辦事項應用程式容器,但加入 --mount 選項以指定儲存卷掛載。為儲存卷命名,並將其掛載到容器內的 /etc/todos,這樣就能捕獲該路徑下建立的所有檔案。

    $ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
    
    注意

    如果您使用的是 Git Bash,則必須為此指令使用不同的語法。

    $ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=//etc/todos getting-started
    

    有關 Git Bash 語法差異的更多詳細資訊,請參閱使用 Git Bash

建立儲存卷

  1. 在 Docker Desktop 中選擇 Volumes
  2. Volumes 中,選擇 Create
  3. todo-db 指定為儲存卷名稱,然後選擇 Create

停止並移除應用程式容器

  1. 在 Docker Desktop 中選擇 Containers
  2. 在該容器的 Actions 欄位中選擇 Delete

啟動掛載了儲存卷的待辦事項應用程式容器

  1. 選擇 Docker Desktop 頂部的搜尋框。

  2. 在搜尋視窗中,選擇 Images 標籤。

  3. 在搜尋框中,指定映像檔名稱 getting-started

    提示

    使用搜尋篩選器僅顯示 Local images

  4. 選擇您的映像檔,然後選擇 Run

  5. 選擇 Optional settings

  6. Host port 中,指定連接埠,例如 3000

  7. Host path 中,指定儲存卷名稱 todo-db

  8. Container path 中,指定 /etc/todos

  9. 選擇 Run

驗證資料持久化

  1. 容器啟動後,開啟應用程式並在您的待辦事項列表中新增幾個項目。

    Items added to todo list
  2. 停止並移除該待辦事項應用程式容器。使用 Docker Desktop 或 docker ps 取得 ID,然後使用 docker rm -f <id> 將其移除。

  3. 使用上述步驟啟動一個新容器。

  4. 開啟應用程式。您應該會看到您的項目仍然在列表中。

  5. 當您確認完列表後,請將容器移除。

您現在已經學會了如何持久化資料。

深入了解儲存卷

許多人經常問:「當我使用儲存卷時,Docker 把我的資料儲存在哪裡?」如果您想知道,可以使用 docker volume inspect 指令。

$ docker volume inspect todo-db

您應該會看到類似以下的輸出

[
    {
        "CreatedAt": "2019-09-26T02:18:36Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

Mountpoint 是資料在磁碟上的實際位置。請注意,在大多數機器上,您需要具備 root 存取權限才能從主機存取此目錄。

總結

在本節中,您學習了如何持久化容器資料。

相關資訊

下一步

接下來,您將學習如何使用綁定掛載 (bind mounts) 更有效率地開發您的應用程式。

使用綁定掛載 (Bind mounts)
© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.