天天看點

docker資料卷

為了能夠儲存(持久化)資料以及共享容器間的資料,Docker提出了Volume的概念。簡單來說,Volume就是目錄或者檔案,它可以繞過預設的聯合檔案系統,而以正常的檔案或者目錄的形式存在于主控端上。

總結:Volume可以将容器以及容器産生的資料分離開來,這樣,當你使用docker  rm  my_container删除容器時,不會影響相關的資料。

我們可以通過兩種方式來初始化Volume,這兩種方式有些細小而又重要的差别。我們可以在運作時使用-v來聲明Volume:

docker管理資料的方式有兩種:

· 資料卷

· 資料卷容器

資料卷是為一個或多個容器專門指定繞過Union File System的目錄,為持續性或共享資料提供一些有用的功能:

· 資料卷可以在容器間共享和重用

· 資料卷資料改變是直接修改的

· 資料卷資料改變不會被包括在容器中

· 資料卷是持續性的,直到沒有容器使用它

資料卷的使用,類似于 Linux 下對目錄進行 mount

挂載一個主機目錄作為資料卷

你想在容器中使用主機上的某個目錄,你可以通過-v參數來指定(注:注意冒号前面的和後面的内容):

docker run -v /host/path:/some/path ...

這明确地告訴Docker使用指定的主機路徑來代替Docker自己建立的根路徑并挂載到容器内指定的路徑(以上例子為/some/path)。需要注意的是,如果主機上的路徑不存在,目錄将自動在給定的路徑中建立。

在用 docker run 指令的時候,可以指定挂載一個本地主機的目錄到容器中去,可以使用多次-v選項為一個 docker 容器運作挂載多個本地主機目錄。

下面建立一個 web 容器,并加載一個主控端目錄到容器的 /var/www/html/目錄

在主控端上建立/web/webapp1目錄,并建立一個index.html檔案,内容如下:

<code>[root@localhost /]</code><code># mkdir -p /web/webqpp1</code>

<code>[root@localhost /]</code><code># cd /web/webqpp1/</code>

<code>[root@localhost webqpp1]</code><code># echo  xinwang &gt; index.html</code>

檢視鏡像:

<code>root@localhost src]</code><code># docker images</code>

<code>[root@localhost src]</code><code># docker tag centos7:http  docker.wang.com/centos:centos7</code>

<code>REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE</code>

<code>centos7             http                a177f7af7a84        3 days ago          337.9 MB</code>

使用鏡像建立容器

<code>root@localhost src]</code><code># docker run -dit -p 80:80 -p 10122:22 -v /web/webqpp1/:/var/www/html/ centos7:http</code>

<code>de64067dec968e6537eb65a75cbcc01a26ad7ad78d6dbe2dd6b31dfb8c22904c</code>

上面的指令加載主機的 /web/webapp1 目錄到容器的 /var/www/html 目錄。這個功能在進行測試的時候十分友善,

比如使用者可以放置一些程式到本地目錄中,來檢視容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你建立它。

/web/webapp1目錄的檔案都将會出現在容器内。這對于在主機和容器之間共享檔案是非常有幫助的,例如挂載需要編譯的源代碼。為了保證可移植性(并不是所有的系統的主機目錄都是可以用的),挂載主機目錄不需要從Dockerfile指定。

挂載的目錄可以通過docker inspect  容器ID

<code>[root@localhost src]</code><code># docker inspect de64067de</code>

<a href="https://s3.51cto.com/wyfs02/M01/A3/66/wKioL1mkGU3grA43AAANkhQCDLk999.png-wh_500x0-wm_3-wmp_4-s_4248769056.png" target="_blank"></a>

在浏覽器中,輸入宿主IP和端口号,即可通路測試頁

<a href="https://s4.51cto.com/wyfs02/M00/04/B5/wKiom1mkGW6i3vLrAAAKhMLsLMI574.png-wh_500x0-wm_3-wmp_4-s_1305633731.png" target="_blank"></a>

-v選項除了可以挂載目前主機的一個目錄到容器中也可以添加一個或多個資料卷

建立一個資料卷

Volume可以使用以下兩種方式建立:

1.在Dockerfile中指定VOLUME  /some/dir

2.執行docker run -v /some/dir指令來指定

無論哪種方式都是做了同樣的事情。它們告訴Docker在主機上建立一個目錄(預設情況下是在/var/lib/docker/volumes下),然後将其挂載到指定的路徑(例子中是:/some/dir)。當删除使用該Volume的容器時,Volume本身不會受到影響,它可以一直存在下去。

如果在容器中不存在指定的路徑,那麼該目錄将會被自動建立。

建立資料卷綁定到到建立容器,建立容器中會建立 /data 資料卷

<code>[root@localhost src]</code><code># docker run -dit -v /data docker.wang.com/centos:centos7</code>

<code>f5f8ac1f8843ea349914615d1876ed30d016c4636cfdc04c8a3f12de6008835a</code>

注意:也可以在 dockerfile 中使用 volume 來添加一個或者多個新的卷到由該 image 建立的任意容器,例如:

FROM debian:wheezy

VOLUME /data

進入容器,檢視給容器添加的資料卷

<code>[root@localhost src]</code><code># docker exec -it  f5f8ac1f8843e /bin/bash</code>

<a href="https://s4.51cto.com/wyfs02/M01/A3/66/wKioL1mkGZ2gwwksAAAsrdyDtrs578.png-wh_500x0-wm_3-wmp_4-s_2949844637.png" target="_blank"></a>

建立的資料卷可以通過docker inspect擷取主控端對應路徑

<code>[root@localhost ~]</code><code># docker inspect  f5f8ac1f8843</code>

<a href="https://s5.51cto.com/wyfs02/M00/A3/66/wKioL1mkGbjB6QTUAAAeoSe89K8677.png-wh_500x0-wm_3-wmp_4-s_2713053337.png" target="_blank"></a>

這說明Docker把在/var/lib/docker下的某個目錄挂載到了容器内的/data目錄下。

注:docker版本及運作的主控端系統不同,資料卷的檢視和對應的具體路徑會有差異。

讓我們從主機上添加檔案到此檔案夾下:

<code>[root@localhost ~]</code><code># cd /var/lib/docker/volumes/6816b5a6a599282ee53801b72006c37189e2e17eb81fef1102a3602a558f5d37/_data/</code>

<code>root@localhost _data]</code><code># touch test-file</code>

進入我們的容器内可以看到:

docker  attach  容器名|容器ID

<code>[root@f5f8ac1f8843 /]</code><code># ls /data/</code>

<code>test</code><code>-</code><code>file</code>

注1:Docker 挂載資料卷的預設權限是讀寫,使用者也可以通過 :ro 指定為隻讀。

<code>[root@localhost ~]</code><code># docker run -it -v /web/webapp1/:/webapp1:ro docker.benet.com/centos7:centos</code>

<code>[root@9e2ab1f6ae8e /]</code><code># echo "hello": &gt; /webapp1/file</code>

<code>bash</code><code>: </code><code>/webapp1/file</code><code>: Read-only </code><code>file</code> <code>system</code>

加了  :ro  之後,就挂載為隻讀了。

資料卷容器

如果要授權一個容器通路另一個容器的Volume,我們可以使用--volumes-from參數來執行

如果你有一些持久性的資料并且想在容器間共享,可以建立一個資料卷容器,然後從此容器上挂載資料。

常見的使用場景是使用純資料容器來持久化資料庫、配置檔案或者資料檔案等。

例如:

docker run --name dbdata postgres echo "Data-only container for postgres"

該指令将會建立一個已經包含在Dockerfile裡定義過Volume的postgres鏡像(如:VOLUME  /var/lib/postgresql/data),運作echo指令然後退出。當我們運作docker  ps指令時,echo可以幫助我們識别某鏡像的用途。我們可以用--volumes-from指令來識别其它容器的Volume:

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

現在就來建立一個命名的資料卷容器:

#docker run -dit -v /test --name data鏡像

<code>[root@localhost ~]</code><code># docker run -dit -v /test --name data docker.benet.com/centos7:centos</code>

<code>39a7e80456c8940f5de1994ca86aa614eacb954cbf56d96b009bcbf07c998a1e</code>

使用--volumes-from選項在另一個容器中挂載 /test 卷。不管 data 容器是否運作,其它容器都可以挂載該容器資料卷,當然如果隻是單獨的資料卷是沒必要運作容器的。

然後,你可以在其他容器中使用 --volumes-from  來挂載/test 卷

#docker run -dit --volumes-from data --name test1鏡像

<code>[root@localhost ~]</code><code># docker run -dit --volumes-from data --name test1 docker.benet.com/centos7:centos</code>

<code>9dc1a49d599ce55215601954762ae3066408c8de42f5182dc9f6f86e19e7f823</code>

注:還可以使用多個 --volumes-from  參數來從多個容器挂載多個資料卷

執行docker ps檢視

<a href="https://s2.51cto.com/wyfs02/M00/04/B5/wKiom1mkGm2gKPtUAAAx16RKlkU552.png-wh_500x0-wm_3-wmp_4-s_809799155.png" target="_blank"></a>

進入test1、test2容器,執行df檢視

<a href="https://s5.51cto.com/wyfs02/M01/04/B5/wKiom1mkGnmToID2AAA31YJQySc312.png-wh_500x0-wm_3-wmp_4-s_4046975237.png" target="_blank"></a>

也可以繼承其它挂載有 /test 卷的容器

<code>[root@localhost ~]</code><code># docker attach  39a7e80456c8</code>

<code>[root@39a7e80456c8 </code><code>test</code><code>]</code><code># touch chaixinwang</code>

<code>[root@39a7e80456c8 </code><code>test</code><code>]</code><code># touch chaixinwang1</code>

<code>[root@39a7e80456c8 </code><code>test</code><code>]</code><code># touch chaixinwang2</code>

<code>[root@39a7e80456c8 </code><code>test</code><code>]</code><code># touch chaixinwang3</code>

如果删除了挂載的容器(包括 data、db1 和 db2),資料卷并不會被自動删除。如果要删除一個資料卷,必須在删除最後一個還挂載着它的容器時使用  docker rm -v  指令來指定同時删除關聯的容器。

利用 Data Volume Container  來備份、恢複、移動資料備份

資料卷另外一個功能是使用他們來備份、恢複、移動資料,如果你在用資料容器,那做備份是相當容易的。

使用 --volume 标記來建立一個加載了卷的新的容器,指令如下:

該示例應該會将Volume裡所有的東西壓縮為一個tar包

<code>[root@localhost ~]</code><code># docker run --rm --volumes-from data -v $(pwd):/backup docker.benet.com/centos7:centos tar cvf /backup/backup.tar /test</code>

<code>tar</code><code>: Removing leading `/' from member names</code>

<code>/test/</code>

<code>/test/chaixinwang</code>

<code>/test/chaixinwang1</code>

<code>/test/chaixinwang2</code>

<code>/test/chaixinwang3</code>

這裡我們建立了一個容器,先從 data 容器來挂載資料卷。然後從本地主機挂載目前目錄到容器的 /backup 目錄。最後,使用 tar 指令來将 data 卷備份為 backup.tar 。當指令執行完、容器停止之後,我們就備份了 data 資料卷

執行完成之後删除容器--rm,此時備份就在目前的目錄下,名為backup.tar

主控端目前目錄下産生了 test 卷的備份檔案 test.tar

<code>[root@39a7e80456c8 /]</code><code># rm -rf test/*</code>

<code>[root@39a7e80456c8 /]</code><code># ls test/</code>

解壓

<code>[root@localhost ~]</code><code># tar tf backup.tar</code>

恢複

<code>[root@localhost ~]</code><code># docker run --volumes-from data -v $(pwd):/backup docker.benet.com/centos7:centos tar xvf /backup/backup.tar -C /</code>

<code>test</code><code>/</code>

<code>test</code><code>/chaixinwang</code>

<code>test</code><code>/chaixinwang1</code>

<code>test</code><code>/chaixinwang2</code>

<code>test</code><code>/chaixinwang3</code>

成功恢複完成

<code>[root@localhost ~]</code><code># docker attach test1</code>

<code>[root@9dc1a49d599c /]</code><code># ls /test/</code>

<code>chaixinwang  chaixinwang1  chaixinwang2  chaixinwang3</code>

附:

權限與許可

通常你需要設定Volume的權限或者為Volume初始化一些預設資料或者配置檔案。要注意的關鍵點是,在Dockerfile的VOLUME指令後的任何指令都不能改變該Volume,比如:

FROM debian:wheezy

RUN useradd foo

VOLUME /data

RUN touch /data/x

RUN chown -R foo:foo /data

該Docker file不能按預期那樣運作,我們本來希望touch指令在鏡像的檔案系統上運作,但是實際上它是在一個臨時容器的Volume上運作。如下所示:

RUN mkdir /data &amp;&amp; touch /data/x

是以,牢記Dockerfile中VOLUME指令的位置(VOLUME是設定指令)

如果你沒有通過RUN指令設定權限,那麼你就需要在容器啟動時使用CMD或ENTRYPOINT指令來執行

删除 Volumes

Volume 隻有在下列情況下才能被删除:

· docker rm -v删除容器時添加了-v選項

例如:你可以告訴Docker同時删除容器和其Volume:

      docker rm -v my_container

· docker run --rm運作容器時添加了--rm選項

即使用以上兩種指令,也隻能删除沒有容器連接配接的Volume。連接配接到使用者指定主機目錄的Volume永遠不會被docker删除。

否則,會在/var/lib/docker/volumes目錄下得到一些僵屍檔案和目錄,并且還不容易說出它們到底代表什麼。

     本文轉自柴鑫旺 51CTO部落格,原文連結:http://blog.51cto.com/chaixinwang/1960284,如需轉載請自行聯系原作者

繼續閱讀