猿學—docker進階篇Volume(數據卷)

引言

docker的鏡像是由多個只讀的文件系統疊加在一起形成的。當我們在我啟動一個容器的時候,docker會加載這些只讀層並在這些只讀層的上面(棧頂)增加一個讀寫層。這時如果修改正在運行的容器中已有的文件,那麼這個文件將會從只讀層複製到讀寫層。該文件的只讀版本還在,只是被上面讀寫層的該文件的副本隱藏。當刪除docker,或者重新啟動時,之前的更改將會消失。在Docker中,只讀層及在頂部的讀寫層的組合被稱為Union File System聯合文件系統)。

為了很好的實現數據保存和數據共享,Docker提出了Volume這個概念,簡單的說就是繞過默認的聯合文件系統,而以正常的文件或者目錄的形式存在於宿主機上。又被稱作數據卷。

Volume的作用

  • 通過數據卷可以在容器之間實現共享和重用
  • 對數據卷的修改會立馬生效(非常適合作為開發環境)
  • 對數據卷的更新,不會影響鏡像
  • 卷會一直存在,直到沒有容器使用

初始化Volume

在使用docker run的時候我們可以通過 -v 來創建一個數據卷並掛載到容器上,在一次run中多次使用可以掛載多個容器。

如果使用Dockerfile方式進行初始化時可以使用 VOLUME 來添加一個或者多個新的捲到由該鏡像創建的任意容器。

創建一個數據卷

docker run -p 8080:80 -d --name shanlei-nginx -v /usr/share/nginx/html nginx

上面的命令的意思是,我們創建了一個名稱為shanlei-nginx的容器,將本機的8080端口映射到容器中nginx服務器的默認web訪問端口80下,創建一個數據卷,並掛載到容器的/usr/share/nginx/html目錄下。

這時我們就可以繞過聯合文件系統,直接在主機上操作該目錄了,任何在該鏡像/usr/share/nginx/html下的文件都會被複制到Volume。

我們可以通過docker inspect指令找到Volume在主機上的存儲位置

docker inspect inspect shanlei-nginx

docker inspect指令後面的參數可以跟容器名稱。通過這個命令我們可以獲得容器所有的相關信息。我們需要看這一部分

...

...

"Mounts": [

{

"Type": "volume",

"Name": "057f911105d4c77d2cfe16ee6acb7f5a43f2643d571708da40f5db55e27b1155",

"Source": "/var/lib/docker/volumes/057f911105d4c77d2cfe16ee6acb7f5a43f2643d571708da40f5db55e27b1155/_data",

"Destination": "/usr/share/nginx/html",

"Driver": "local",

"Mode": "",

"RW": true,

"Propagation": ""

}

],

...

...

這說明docker把本機的“Source”指向目錄,也就是

/var/lib/docker/volumes/057f911105d4c77d2cfe16ee6acb7f5a43f2643d571708da40f5db55e27b1155/_data

掛載到了容器的“Destination”指向的目錄。

在Linux中我們可以直接進入“Source”指向的路徑(注意在訪問該目錄時可能會有權限問題)

猿學—docker進階篇Volume(數據卷)

只要將主機的目錄掛載到容器的目錄上,那改變就會立即生效。在Dockerfile中我們可以通過VOLUME達到相同的目的

FROM nginx

VOLUME /usr/share/nginx/html

目錄作為數據卷

通過-v標識可以將主機的目錄掛載到容器中去

sudo docker run -d -p 8080:80 -v $PWD/html:/usr/share/nginx/html nginx

上面的命令將本機的$PWD/html目錄掛載到容器的/usr/share/nginx/html目錄。$PWD在是一個系統環境變量,指代當前目錄環境。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你創建它。

注意:Dockerfile中不支持這種語法.

docker掛載數據卷的默認權限是讀寫,當然我們可以通過指令:ro指定為只讀。

sudo docker run -d -p 8080:80 -v $PWD/html:/usr/share/nginx/html:ro nginx

在我的本機主機的$PWD/html中有一個index.html文件,內容如下:

this is old

我們運行上面的命令,並將本機8080端口映射到容器中nginx服務器的默認web端口80下,現在我們來訪問localhost:8080

猿學—docker進階篇Volume(數據卷)

現在我們修改本機下的$PWD/html/index.html

this is new

訪問localhost:8080

猿學—docker進階篇Volume(數據卷)

文件作為數據卷

我們也可以使用-v指令從主機掛載單個文件到容器中去

docker run -d -p 8080:80 -v $PWD/html/index.html:/usr/share/nginx/html/index.html nginx

當修改本機$PWD/html/index.html時,容器中的/usr/share/nginx/html/index.html也會隨之變化。效果和上面相同,在這裡就不做贅述了。

注意:如果直接掛載一個文件,很多文件編輯工具,包括 vi 或者 sed --in-place ,可能會造成文件 inode的改變,從 Docker 1.1 .0起,這會導致報錯誤信息。所以最簡單的辦法就直接掛載文件的父目錄。

數據共享

如果想要實現容器間的數據共享,那麼需要授權一個容器訪問另一個容器的Volume。我們可以在使用docker run時使用-volumes-from參數來進行指定。

docker run -it -h NEWCONTAINER --volumes-from shanlei-nginx ubuntu /bin/bash

猿學—docker進階篇Volume(數據卷)

注意:值得注意的是不管shanlei-nginx是否運行,它都會起作用。只要有容器連接Volume,它就不會被刪除。

數據卷容器

如果我們有一些持續更新的數據需要在容器之間共享,最好創建數據卷容器。常見的使用場景是使用純數據容器來持久化數據庫、配置文件或者數據文件等。

數據卷容器,其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。

首先我們需要先創建一個數據卷容器

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

猿學—docker進階篇Volume(數據卷)

然後通過--volumes-from指令參數來掛載 dbdata 容器中的數據卷。

docker run -d --volumes-from dbdata --name db1 training/postgres

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

來掛載數據卷。

docker run -d --name db3 --volumes-from db1 training/postgres

現在我們進入容器中查看數據卷容器是否掛載成功

docker exec -it db1 /bin/bash

猿學—docker進階篇Volume(數據卷)

說明數據卷容器掛載已經成功了。

注意:如果刪除了掛載的容器(包括 dbdata、db1 和 db2等),數據卷並不會被自動刪除。如果要刪除一個數據卷,必

須在刪除最後一個還掛載著它的容器時使用 docker rm -v 命令來指定同時刪除關聯的容器。

備份和恢復

我們可以利用數據卷對其中的數據進行進行備份、恢復和遷移。

首先使用 --volumes-from 標記來創建一個加載 dbdata 容器卷的容器,並從本地主機掛載當前到容器的 /backup 目錄。命令如下:

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

容器啟動後,使用了 tar 命令來將 dbdata 卷備份為本地的 /backup/backup.tar 。

恢復

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

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

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

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


分享到:


相關文章: