持久化資料庫

如果您沒有注意到,您的待辦事項列表在每次啟動容器時都是空的。這是為什麼呢?在本部分中,您將深入瞭解容器的工作原理。

容器的檔案系統

當容器執行時,它使用來自映象的各個層作為其檔案系統。每個容器還會獲得自己的“暫存空間”來建立/更新/刪除檔案。任何更改都不會在另一個容器中看到,即使它們使用的是相同的映象。

在實踐中瞭解

為了實際觀察這一點,您將啟動兩個容器。在一個容器中,您將建立一個檔案。在另一個容器中,您將檢查該檔案是否存在。

  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 檔案在第二個容器中不存在。這是因為每個容器的可寫“頂層”是隔離的。儘管兩個容器共享構成基礎映象的相同底層,但可寫層對每個容器來說是唯一的。

容器卷

透過之前的實驗,您看到每個容器每次啟動時都從映象定義開始。雖然容器可以建立、更新和刪除檔案,但當您移除容器時,這些更改會丟失,並且 Docker 會將所有更改隔離到該容器中。使用卷,您可以改變這一切。

提供了將容器的特定檔案系統路徑連接回宿主機的能力。如果您在容器中掛載一個目錄,該目錄中的更改也會在宿主機上看到。如果您在容器重啟之間掛載同一個目錄,您會看到相同的檔案。

卷主要有兩種型別。您最終會使用這兩種型別,但您將從卷掛載開始。

持久化待辦事項資料

預設情況下,待辦事項應用程式將其資料儲存在容器檔案系統中 /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. 選擇執行

驗證資料是否持久化

  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 許可權才能從主機訪問此目錄。

摘要

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

相關資訊

後續步驟

接下來,您將學習如何使用繫結掛載更有效地開發您的應用。

使用繫結掛載