看誰還不懂 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 容器,並嘗試掛載該數據卷,掛載命令支持兩種:
-v
docker run -d -it --name=test-nginx -p 8011:80 -v test-vol:/usr/share/nginx/html nginx:1.13.12
參數說明:
-
-d
: 後臺運行容器; -
--name=test-nginx
: 指定容器名爲 test-nginx; -
-p 8011:80
: 將容器的 80 端口掛載到宿主機的 8011 端口; -
-v test-vol:/usr/share/nginx/html
: 將test-vol
數據卷掛載到容器中的 /usr/share/nginx/html 目錄上;
--mount
docker run -d -it --name=test-nginx -p 8011:80 --mount source=test-vol,target=/usr/share/nginx/html nginx:1.13.12
參數說明:
--mount source=test-vol,target=/usr/share/nginx/html
: 將test-vol
數據卷掛載到容器中的 /usr/share/nginx/html 目錄上;
-v
和 --mount
有什麼區別?
都是掛載命令,使用 -v
掛載時,如果宿主機上沒有指定文件不會報錯,會自動創建指定文件;當使用 --mount
時,如果宿主機中沒有這個文件會報錯找不到指定文件,不會自動創建指定文件。
容器運行成功後,進入到 /var/lib/docker/volumes
目錄下,驗證數據是否掛載成功:
驗證數據卷是否掛載成功
可以看到已經有了 50x.html
、 index.html
兩個 Nginx 頁面相關數據,說明數據卷掛載成功了。掛載成功後,我們不論是修改 /var/lib/docker/volumes
下的數據,還是進入到容器中修改 /usr/share/nginx/html
下的數據,都會同步修改對應的掛載目錄,類似前端開發中雙向綁定的作用。
下面,我們停止並刪除剛剛運行的 Nginx 容器, 看看數據卷中的數據是否會跟着被刪除:
刪除容器,驗證數據卷是否還存在
可以發現數據卷相關數據都還在,表明數據卷的生命週期獨立於容器。另外,若下次再創建 Nginx 容器,還可以複用這個數據卷,複用性以及擴張性都非常不錯。
刪除數據卷
由於數據卷的生命期獨立於容器,想要刪除數據卷,就需要我們手動來操作, 執行命令如下:
docker volume rm test-vol
如果你需要在刪除容器的同時移除數據卷,請使用
docker rm -v
命令。對於那些沒有被使用的數據卷,可能會佔用較多的磁盤空間,你可以通過如下命令統一刪除:
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
參數說明:
-v /docker/nginx1:/usr/share/nginx/html
: 將宿主機中的/docker/nginx1
目錄掛載到容器中的/usr/share/nginx/html
目錄;
容器運行成功後,進入容器中:
docker exec -it test-nginx /bin/bash
docker 進入容器
從上圖可以看到,與 volume 不同,bind mount 這種方式會隱藏目錄中的內容(非空情況下),這裏的 /usr/share/nginx/html
目錄下的 html 文件被隱藏了,所以我們看不到。
但是,我們可以將宿主機中該目錄中的文件立刻掛載到容器中,下面驗證一下:
- 新建一個
index.html
:
創建 index.html 文件
- 再次進入容器,查看掛載目錄內容:
進入 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