一起研究系列:容器-Docker Volume

想要了解Docker Volume,首先我們需要知道Docker的文件系統是如何工作的。Docker鏡像是由多個文件系統(只讀層)疊加而成。當我們啓動一個容器的時候,Docker會加載只讀鏡像層並在其上(即鏡像棧頂部)添加一個讀寫層。如果運行中的容器修改了現有的一個已經存在的文件,那該文件將會從讀寫層下面的只讀層複製到讀寫層,該文件的只讀版本仍然存在,只是已經被讀寫層中該文件的副本所隱藏。當刪除Docker容器,並通過該鏡像重新啓動時,之前的更改將會丟失。在Docker中,只讀層及在頂部的讀寫層的組合被稱爲Union File System(聯合文件系統)。

爲了能夠保存(持久化)數據以及共享容器間的數據,Docker提出了Volume的概念。簡單來說,Volume就是目錄或者文件,它可以繞過默認的聯合文件系統,而以正常的文件或者目錄的形式存在於宿主機上。

總結:Volume可以將容器以及容器產生的數據分離開來,當你使用docker  rm  my_container刪除容器時,不會影響相關的數據。

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

docker管理數據的方式有兩種:

· 數據卷(Data Volumes)

· 數據卷容器(Data Volumes Containers)

數據卷:

數據卷是爲一個或多個容器專門指定繞過Union File System的目錄,位於容器中,可將宿主機的目錄掛載到數據捲上,對數據卷的修改操作立刻可見,並且更新數據不會影響鏡像,從而實現數據在宿主機與容器之間的遷移,爲持續性或共享數據提供一些有用的功能,數據卷的使用,類似於Linux下對目錄進行的mount操作

· 數據卷可以在容器間共享和重用

· 數據卷數據改變是直接修改的

· 數據卷數據改變不會被包括在容器中

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

1、創建數據卷

在docker run 命令中使用-v選項可以在容器中創建數據卷。多次使用-v選項可以創建多個數據卷。例如:

[root@docker01 ~]# docker run -itd -v /data1 -v /date2 --name web003 centos:httpv1

90030942574d6b47b6be2922a86b38f7483956f6231ab5e30fccc9d4431f61ec

進入容器web003,可以看到兩個數據卷已經創建成功並分別掛載到/data1與/date2上

clip_image002

可以使用docker inspect web003查看到掛載的數據卷

[root@docker01 ~]# docker inspect web003

clip_image004

用戶也可以在Dockerfile中指定數據卷:

例如:

FROM debian:wheezy

VOLUME  /data

注1:Docker 掛載數據卷的默認權限是讀寫,用戶也可以通過 :ro 指定爲只讀。

例如:

clip_image006

2、掛載主機目錄作爲數據卷

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

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

這明確地告訴Docker使用指定的主機路徑來代替Docker自己創建的根路徑並掛載到容器內指定的路徑(以上例子爲/some/path)。需要注意的是,宿主機本地目錄上的路徑必須使用絕對路徑,如果主機上的路徑不存在,目錄將自動在給定的路徑中創建。

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

實例:

1、在宿主機上創建/web/webapp1目錄,並創建一個index.html文件,內容如下:

[root@docker01 ~]# mkdir /web/webapp1 -p

[root@docker01 ~]# cd /web/webapp1/

[root@docker01 webapp1]# echo "<h1> hello world</h1>" >> index.html

[root@docker01 webapp1]# cat index.html

<h1> hello world</h1>

[root@docker01 webapp1]#

2、使用帶有apache服務的一個鏡像,生成容器

[root@docker01 ~]# docker run -itd -v /web/webapp1/:/var/www/html/ -p 8000:80 --name web005 centos:httpv1

clip_image008

3、訪問容器的網站服務:

clip_image010

上面的命令加載主機的 /web/webapp1 目錄到容器的 /var/www/html 目錄。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動爲你創建它。/web/webapp1目錄的文件都將會出現在容器內。這對於在主機和容器之間共享文件是非常有幫助的,例如掛載需要編譯的源代碼。爲了保證可移植性(並不是所有的系統的主機目錄都是可以用的),掛載主機目錄不需要從Dockerfile指定。

數據卷容器:

如果需要在容器之間共享一些數據,最簡單的方法就是使用數據卷容器。數據卷容器就是一個普通的容器,專門提供數據卷給其它容器掛載使用。

使用方法如下:首先,需要創建一個容器作爲數據卷容器,之後在其它容器創建時用--volumes-from掛載數據卷容器中的數據卷使用。

常見的使用場景是使用純數據卷容器來持久化數據庫、配置文件或者數據文件等。

例如:

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

該命令將會使用一個已經包含在Dockerfile裏定義過Volume的postgres鏡像來生成一個容器dbdata(如: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 鏡像

clip_image012

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

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

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

clip_image014

再添加一個容器:

clip_image016

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

執行docker ps查看

clip_image018

進入test1、test2容器,執行df查看

clip_image020

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

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

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

利用 Data Volume Container來備份、恢復、移動數據

備份

數據卷另外一個功能是使用他們來備份、恢復、移動數據,如果你在用數據容器,那做備份是相當容易的。使用 --volume 標記來創建一個加載了卷的新的容器,命令如下:

該示例應該會將Volume裏所有的東西壓縮爲一個tar包

[root@docker01 ~]# docker run --rm --volumes-from data -v $(pwd):/backup centos:httpv1 tar cvf /backup/backup.tar /test

clip_image022

這裏我們創建了一個容器,先從data容器來掛載數據卷。然後從本地主機掛載當前目錄到容器的 /backup 目錄。最後,使用tar命令來將data 卷備份爲backup.tar 。當命令執行完、容器停止之後,我們就備份了 data 數據卷

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

宿主機當前目錄下產生了test卷的備份文件test.tar

clip_image024

clip_image026

恢復

clip_image028

附:

權限與許可

通常你需要設置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上運行。如下所示:

FROM debian:wheezy

RUN useradd foo

RUN mkdir /data && touch /data/x

RUN chown -R foo:foo /data

VOLUME /data

所以,牢記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目錄下得到一些殭屍文件和目錄,並且還不容易說出它們到底代表什麼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章