1. 程式人生 > >docker數據卷

docker數據卷

docker數據卷

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

為了能夠保存(持久化)數據以及共享容器間的數據,

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文件,內容如下:

[[email protected] /]# mkdir -p /web/webqpp1
[[email protected] /]# cd /web/webqpp1/
[[email protected] webqpp1]# echo  xinwang > index.html

查看鏡像:

[email protected] src]# docker images
[[email protected] src]# docker tag centos7:http  docker.wang.com/centos:centos7
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos7             http                a177f7af7a84        3 days ago          337.9 MB

使用鏡像創建容器

[email protected] src]# docker run -dit -p 80:80 -p 10122:22 -v /web/webqpp1/:/var/www/html/ centos7:http
de64067dec968e6537eb65a75cbcc01a26ad7ad78d6dbe2dd6b31dfb8c22904c

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

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

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

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

[[email protected] src]# docker inspect de64067de

技術分享

在瀏覽器中,輸入宿主IP和端口號,即可訪問測試頁

技術分享

-v選項除了可以掛載當前主機的一個目錄到容器中可以添加一個或多個數據

創建一個數據卷

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

1.Dockerfile中指定VOLUME /some/dir

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

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

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

創建數據卷綁定到到新建容器,新建容器中會創建 /data 數據卷

[[email protected] src]# docker run -dit -v /data docker.wang.com/centos:centos7
f5f8ac1f8843ea349914615d1876ed30d016c4636cfdc04c8a3f12de6008835a

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

FROM debian:wheezy

VOLUME /data

進入容器,查看給容器添加的數據卷

[[email protected] src]# docker exec -it  f5f8ac1f8843e /bin/bash

技術分享

創建的數據卷可以通過docker inspect獲取宿主機對應路徑

[[email protected] ~]# docker inspect  f5f8ac1f8843

技術分享

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

註:docker版本及運行的宿主機系統不同,數據卷的查看和對應的具體路徑會有差異。

讓我們從主機上添加文件到此文件夾下:

[[email protected] ~]# cd /var/lib/docker/volumes/6816b5a6a599282ee53801b72006c37189e2e17eb81fef1102a3602a558f5d37/_data/
[email protected] _data]# touch test-file

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

docker attach 容器名|容器ID

[[email protected] /]# ls /data/
test-file

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

[[email protected] ~]# docker run -it -v /web/webapp1/:/webapp1:ro docker.benet.com/centos7:centos
[[email protected] /]# echo "hello": > /webapp1/file
bash: /webapp1/file: Read-only file system

加了 :ro 之後,就掛載為只讀了。

數據卷容器

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

如果你有一些持久性的數據並且想在容器間共享,可以創建一個數據卷容器,然後從此容器上掛載數據。

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

例如:

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

該命令將會創建一個已經包含在Dockerfile裏定義過Volumepostgres鏡像(如: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鏡像

[[email protected] ~]# docker run -dit -v /test --name data docker.benet.com/centos7:centos
39a7e80456c8940f5de1994ca86aa614eacb954cbf56d96b009bcbf07c998a1e

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

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

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

[[email protected] ~]# docker run -dit --volumes-from data --name test1 docker.benet.com/centos7:centos
9dc1a49d599ce55215601954762ae3066408c8de42f5182dc9f6f86e19e7f823

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

執行docker ps查看

技術分享

進入test1test2容器,執行df查看

技術分享

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

[[email protected] ~]# docker attach  39a7e80456c8
[[email protected] test]# touch chaixinwang
[[email protected] test]# touch chaixinwang1
[[email protected] test]# touch chaixinwang2
[[email protected]456c8 test]# touch chaixinwang3

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

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

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

使用 --volume 標記來創建一個加載了卷的新的容器,命令如下:

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

[[email protected] ~]# docker run --rm --volumes-from data -v $(pwd):/backup docker.benet.com/centos7:centos tar cvf /backup/backup.tar /test
tar: Removing leading `/‘ from member names
/test/
/test/chaixinwang
/test/chaixinwang1
/test/chaixinwang2
/test/chaixinwang3

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

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

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

[[email protected] /]# rm -rf test/*
[[email protected] /]# ls test/

解壓

[[email protected] ~]# tar tf backup.tar

恢復

[[email protected] ~]# docker run --volumes-from data -v $(pwd):/backup docker.benet.com/centos7:centos tar xvf /backup/backup.tar -C /
test/
test/chaixinwang
test/chaixinwang1
test/chaixinwang2
test/chaixinwang3

成功恢復完成

[[email protected] ~]# docker attach test1
[[email protected] /]# ls /test/
chaixinwang  chaixinwang1  chaixinwang2  chaixinwang3

附:

權限與許可

通常你需要設置Volume的權限或者為Volume初始化一些默認數據或者配置文件。要註意的關鍵點是,在DockerfileVOLUME指令後的任何指令都不能改變該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

所以,牢記DockerfileVOLUME指令的位置(VOLUME是設置指令)

如果你沒有通過RUN指令設置權限,那麽你就需要在容器啟動時使用CMDENTRYPOINT指令來執行

刪除 Volumes

Volume 只有在下列情況下才能被刪除:

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

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

docker rm -v my_container

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

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

否則,會在/var/lib/docker/volumes目錄下得到一些僵屍文件和目錄,並且還不容易說出它們到底代表什麽


本文出自 “chaixinwang” 博客,請務必保留此出處http://chaixinwang.blog.51cto.com/13052229/1960284

docker數據卷