看誰還不懂 Docker 數據卷 !

大家好,我是小哈~

今天分享的主題是 Docker 數據卷。本文首發至犬小哈教程網:www.quanxiaoha.com

一、什麼是數據卷?

簡單來說,數據卷是一個可供一個或多個容器使用的特殊目錄,用於持久化數據以及共享容器間的數據,它以正常的文件或目錄的形式存在於宿主機上。 另外,其生命週期獨立於容器的生命週期,即當你刪除容器時,數據卷並不會被刪除。

二、爲什麼需要數據卷?

Docker 鏡像由多個文件系統(只讀層)疊加而成。Docker 會加載只讀鏡像層,並在鏡像棧頂部添加一個讀寫層。當運行容器後,如果修改了某個已存在的文件,那麼該文件將會從下面的只讀層複製到上面的讀寫層,同時,該文件在只讀層中仍然存在。當我們刪除 Docker 容器,並通過鏡像重新啓動容器時,之前的更改的文件將會丟失。

那麼,要如何解決數據持久化的問題呢?於是,Docker 提出了 Volume 數據卷的概念。

三、數據卷特性

四、掛載數據卷

Docker 提供了 3 種不同的方式將數據從宿主機掛載到容器中。

Docker 掛載數據卷

4.1 volume (最常用的方式)

volume : Docker 管理宿主機文件系統的一部分,默認位於 /var/lib/docker/volumes 目錄下, 也是最常用的方式。

Docker 查看本地數據卷

看上圖,所有的 Docker 容器數據都保存在 /var/lib/docker/volumes 目錄下。若容器運行時未指定數據卷, Docker 創建容器時會使用默認的匿名卷(名稱爲一堆很長的 ID)。

注意:Mac 系統中, Docker 是基於虛擬機的 ,必須登錄到虛擬機裏面,登錄後在目錄 /var/lib/docker/volumes/ 下即可找到數據卷。

4.2 bind mount(比較常用的方式

bind mount: 意爲可以存儲在宿主機中的任意位置。需要注意的是,bind mount 在不同的宿主機系統時不可移植的,比如 Windows 和 Linux 的目錄結構是不一樣的,bind mount 所指向的 host 目錄也不一樣。這也是爲什麼 bind mount 不能出現在 Dockerfile 中的原因所在,因爲這樣 Dockerfile 就不可移植了。

4.3 tmpfs mount (一般不用這種方式)

tmpfs mount : 掛載存儲在宿主機的內存中,而不會寫入宿主機的文件系統,一般不用此種方式。

五、Volume 使用

5.1 創建一個數據卷

執行如下命令創建數據卷:

docker volume create test-vol

Docker 創建數據卷

5.2 查看所有的數據卷

docker volume ls

Docker 查看當前已創建的數據卷

5.3 查看數據卷信息

執行如下命令,可以查看指定的數據卷信息:

# 查看數據卷名爲 test-vol 的信息
docker volume inspect test-vol

Docker 查看數據卷信息

5.4 運行容器時掛載數據卷

數據卷 test-vol創建成功後,我們運行一個 Nginx 容器,並嘗試掛載該數據卷,掛載命令支持兩種:

  1. -v
docker run -d -it --name=test-nginx -p 8011:80 -v test-vol:/usr/share/nginx/html nginx:1.13.12

參數說明:

  1. --mount
docker run -d -it --name=test-nginx -p 8011:80 --mount source=test-vol,target=/usr/share/nginx/html nginx:1.13.12

參數說明:

-v--mount 有什麼區別?

都是掛載命令,使用 -v 掛載時,如果宿主機上沒有指定文件不會報錯,會自動創建指定文件;當使用 --mount時,如果宿主機中沒有這個文件會報錯找不到指定文件,不會自動創建指定文件。


容器運行成功後,進入到 /var/lib/docker/volumes 目錄下,驗證數據是否掛載成功:

驗證數據卷是否掛載成功

可以看到已經有了 50x.htmlindex.html 兩個 Nginx 頁面相關數據,說明數據卷掛載成功了。掛載成功後,我們不論是修改 /var/lib/docker/volumes 下的數據,還是進入到容器中修改 /usr/share/nginx/html 下的數據,都會同步修改對應的掛載目錄,類似前端開發中雙向綁定的作用。

下面,我們停止並刪除剛剛運行的 Nginx 容器, 看看數據卷中的數據是否會跟着被刪除:

刪除容器,驗證數據卷是否還存在

可以發現數據卷相關數據都還在,表明數據卷的生命週期獨立於容器。另外,若下次再創建 Nginx 容器,還可以複用這個數據卷,複用性以及擴張性都非常不錯。

刪除數據卷

由於數據卷的生命期獨立於容器,想要刪除數據卷,就需要我們手動來操作, 執行命令如下:

docker volume rm test-vol
  1. 如果你需要在刪除容器的同時移除數據卷,請使用 docker rm -v 命令。

  2. 對於那些沒有被使用的數據卷,可能會佔用較多的磁盤空間,你可以通過如下命令統一刪除:

docker volume prune

bind mount 使用

通過 bind mount 模式可以掛載到宿主機的任意位置,示例如下:

docker run -d -it --name=test-nginx -p 8011:80 -v /docker/nginx1:/usr/share/nginx/html nginx:1.13.12

參數說明:

容器運行成功後,進入容器中:

docker exec -it test-nginx /bin/bash

docker 進入容器

從上圖可以看到,與 volume 不同,bind mount 這種方式會隱藏目錄中的內容(非空情況下),這裏的 /usr/share/nginx/html 目錄下的 html 文件被隱藏了,所以我們看不到。

但是,我們可以將宿主機中該目錄中的文件立刻掛載到容器中,下面驗證一下:

  1. 新建一個 index.html:

創建 index.html 文件

  1. 再次進入容器,查看掛載目錄內容:

進入 docker 容器

數據卷容器

如果你有一些需要持續更新的數據需要在容器之間共享,最佳實踐是創建數據卷容器。數據卷容器,其實就是一個正常的 Docker 容器,專門用於提供數據卷供其他容器掛載的

創建數據卷容器

運行一個容器,並創建一個名爲 dbdata 的數據卷:

docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres

Docker 創建數據卷容器

容器運行成功後,會發現該數據卷容器處於停止運行狀態,這是因爲數據卷容器並不需要處於運行狀態,只需用於提供數據卷掛載即可。

掛載數據卷

--volumes-from 命令支持從另一個容器掛載容器中已創建好的數據卷。

docker run -d --volumes-from dbdata --name db1 training/postgres
docker run -d --volumes-from dbdata --name db2 training/postgres
docker ps
CONTAINER ID       IMAGE                COMMAND                CREATED             STATUS              PORTS               NAMES
7348cb189292       training/postgres    "/docker-entrypoint.   11 seconds ago      Up 10 seconds       5432/tcp            db2
a262c79688e8       training/postgres    "/docker-entrypoint.   33 seconds ago      Up 32 seconds       5432/tcp            db1

還可以使用多個 --volumes-from 參數來從多個容器掛載多個數據卷。也可以從其他已經掛載了數據卷的容器來掛載數據卷。

如果刪除了掛載的容器(包括 dbdata、db1 和 db2),數據卷並不會被自動刪除。如果想要刪除一個數據卷,必須在刪除最後一個還掛載着它的容器時使用 docker rm -v 命令來指定同時刪除關聯的容器。

使用數據卷容器備份、恢復、遷移數據卷

本小節中,我們將學習如何對數據卷容器中的數據進行進行備份、恢復和遷移。

備份

首先使用 --volumes-from 命令創建一個加載 dbdata 的容器卷容器,並將宿主機當前目錄掛載到容器的 /backup 目錄,命令如下:

$ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

容器啓動後,使用了 tar 命令來將 dbdata 數據卷備份爲容器中 /backup/backup.tar 文件,因爲掛載了的關係,宿主機的當前目錄下也會生成 backup.tar 備份文件。

恢復 / 遷移

如果要恢復數據到一個容器,首先創建一個帶有空數據卷的容器 dbdata2。

$ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

然後創建另一個容器,掛載 dbdata2 容器卷中的數據卷,並使用 untar 解壓備份文件到掛載的容器卷中。

$ sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf
/backup/backup.tar

爲了查看 / 驗證恢復的數據,可以再啓動一個容器掛載同樣的容器捲來查看:

$ sudo docker run --volumes-from dbdata2 busybox /bin/ls /dbdata
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/OXsbY78T3XWVTzt1Il7quw