docker系列(四):數據卷

1 引言

容器就至關於一個簡易的操做系統,咱們在上面部署咱們的環境,不可避免地產生一些數據,可是,可能因爲斷電等等緣由,容器退出了,那麼以前容器中的數據就不符存在,則每每不是咱們想要的,更多的,咱們是但願數據可以持久保存到硬盤中,這就須要用到數據卷。docker

數據卷是指一種目錄或者說文件,其存在於一個或者多個容器中,由docker掛載到容器,但不屬於UFS(Union File System,聯合文件系統),所以可以繞開UFS提供一些用於持續存儲或共享數據的特性。ubuntu

數據卷的設計目的就是爲了實現數據的持久化,徹底獨立於容器的生存週期,所以docker不會在容器刪除時刪除其掛載的數據卷。除此之外,數據卷還能夠實現容器間的數據繼承和共享。在使用上,數據卷的特色:bash

 

  • 數據卷能夠在容器之間共享或者重用數據
  • 數據卷中的更改能夠直接生效
  • 數據卷中的更改不會包含在鏡像的更新中
  • 數據卷的生命週期一直持續到沒有容器使用它爲止

 

下面就開始來研究一下添加數據卷。添加數據卷有兩種方法,第一種是經過命令直接添加,第二種是經過dockerfile添加。ide

2 數據卷

2.1 經過命令添加數據卷

在上一篇博文中,提到過docker run命令,docker run命令中有一個參數-v就是用來添加數據卷的,也就是說,在docker run命令中使用-v參數,能夠在啓動容器時,爲容器添加一個數據卷。命令格式以下:ui

docker run -it -v /宿主機絕對路徑目錄:/容器內絕對 鏡像名spa

主義,命令中使用的路徑最好使用絕對路徑,不然可能會報錯。另外,有的時候,可能會省略宿主機路徑,只寫容器內的數據卷路徑,這時候,docker會在/var/lib/docker/volumes/目錄下自行建立一個目錄最爲主機數據卷目錄。操作系統

例如將宿主機的當前用戶目錄下名爲suzu的目錄,與容器內根目錄下名爲rongqi的目錄進行映射做爲數據卷。命令行

$ docker run -it -v ~/suzhu:/rongqi ubuntu

root@fd4af8e0b8b3:/#

啓動容器後,咱們查看一下容器內是否有容器這一目錄:設計

root@fd4af8e0b8b3:/# ll rongqi
total 8
drwxr-xr-x 2 root root 4096 Jun 15 02:36 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:36 ../
發現存在rongqi目錄。繼續,咱們在容器內建立一個名爲123的文件,看看宿主機內是否會同步這一文件:
root@fd4af8e0b8b3:/# cd rongqi
root@fd4af8e0b8b3:/rongqi# touch 123
root@fd4af8e0b8b3:/rongqi# ll
total 8
drwxr-xr-x 2 root root 4096 Jun 15 02:40 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:40 ../
-rw-r--r-- 1 root root 0 Jun 15 02:40 123
在宿主機啓動另外一個終端,查看是否同步:
$ cd ~/suzhu
~/suzhu$ ll
total 8
drwxr-xr-x 2 root root 4096 Jun 15 10:40 ./
drwxr-xr-x 16 chb chb 4096 Jun 15 10:41 ../
-rw-r--r-- 1 root root 0 Jun 15 10:40 123

看到了沒,宿主機rongqi目錄中也同步出現了123文件。並且,不管是宿主機的容器目錄仍是容器內的rongqi目錄都是由docker自動建立的。code

再次,咱們嘗試在宿主機中修改123文件的內容,看容器內的123文件是否會修改,注意必定要使用超級管理員權限進行寫入才行,這時候主機只有只讀權限。以下圖所示:

保存後退出,再次回到容器內查看123文件內容:

root@fd4af8e0b8b3:/rongqi# tac 123
我是宿主機,我寫入了一行

證實宿主機與容器的同步是雙向的。

若是容器中止了,宿主機添加文件,是否會在容器從新啓動後同步到呢?

咱們先中止容器,而後在宿主機suzhu目錄下建立一個111.txt文件:

root@fd4af8e0b8b3:/rongqi# exit
exit
$ cd ~/suzhu
$ touch 111.txt
$ sudo touch 111.txt

啓動剛剛的容器,看看是否出現111.txt文件:

$ docker start fd4af8e0b8b3
fd4af8e0b8b3
$ docker attach fd4af8e0b8b3
root@fd4af8e0b8b3:/# cd rongqi
root@fd4af8e0b8b3:/rongqi# ll
total 12
drwxr-xr-x 2 root root 4096 Jun 15 03:07 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:40 ../
-rw-r--r-- 1 root root 0 Jun 15 03:07 111.txt
-rw-r--r-- 1 root root 37 Jun 15 02:55 123

看到了嗎?在容器重啓後,在rongqi目錄下也出現了111.txt文件。

一個容器能夠有多個數據卷嗎?

答案是能夠的。須要指定多個-v參數來實現。

$ docker run -it -v ~/suzhu:/rongqi -v ~/suzhu2:/rongqi2 ubuntu

繼續研究,一個目錄能夠掛載多個數據卷嗎?

$ docker run -it -v ~/suzhu:/rongqi ubuntu
root@deb66cd44a57:/#

容器建立成功。咱們繼續嘗試使用新建的容器,看看容器間的數據卷內文件是否會同步:

root@deb66cd44a57:/# cd rongqi
root@deb66cd44a57:/rongqi# ll
total 12
drwxr-xr-x 2 root root 4096 Jun 15 03:07 ./
drwxr-xr-x 1 root root 4096 Jun 15 03:40 ../
-rw-r--r-- 1 root root 0 Jun 15 03:07 111.txt
-rw-r--r-- 1 root root 37 Jun 15 02:55 123
root@deb66cd44a57:/rongqi# touch 222.txt

去最初建立的容器中查看:

$ docker attach fd4af8e0b8b3
root@fd4af8e0b8b3:/rongqi# ll
total 12
drwxr-xr-x 2 root root 4096 Jun 15 03:43 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:40 ../
-rw-r--r-- 1 root root 0 Jun 15 03:07 111.txt
-rw-r--r-- 1 root root 37 Jun 15 02:55 123
-rw-r--r-- 1 root root 0 Jun 15 03:43 222.txt

文件同步了。證實一個目錄能夠被多個容器掛在爲數據卷,從而實現容器間的數據同步和共享。

既然一個目錄能夠被多個容器掛在爲數據卷,就須要涉及權限的問題了,例若有的容器須要有讀和寫的權限,可是,有的容器,只須要有讀不能由寫入權限,這該怎麼辦呢?其實只須要掛在目錄後面加入權限參數就行了,參數中,rw表示有讀和寫權限,ro表示只有du的權限,在默認狀況下,是rw就同時具備讀寫權限。咱們繼續建立一個容器,對suzhu目錄只有只讀權限,而後嘗試在容器中建立文件:

$ docker run -it -v ~/suzhu:/rongqi:ro ubuntu
root@6df9eaeb444a:/# cd rongqi
root@6df9eaeb444a:/rongqi# touch 333.txt
touch: cannot touch '333.txt': Read-only file system
建立文件失敗,由於只有只讀的權限。
總結一下在docker run命令中添加數據卷的內容:
  • 在docker run命令中添加-v 宿主機目錄:容器目錄參數形式進行添加數據卷
  • 若是目錄不存在,docker會自動建立
  • 同步是雙向的
  • 若是不對權限進行制定,宿主機只有只讀權限
  • 容器重啓並不影響同步
  • 經過多個-v參數,一個容器掛載多個數據卷
  • 一個目錄能夠被多個容器掛載,從而實現容器間的數據共享同步。
  • 經過rw和ro參數,能夠指定容器對數據卷的讀寫權限。
  • 指定數據卷目錄時,最好使用絕對路徑,不要使用相對路徑(上面並無演示)

2.2 經過dockerfile添加數據卷

dockerfile內容在前面的博文中已經介紹過了。在dockerfile中有一個專門的命令VOLUME是用來添加數據卷的,VOLUME命令格式以下:

VOLUME ["數據卷目錄1", "數據卷目錄2"]

注意:數據卷目錄1和2都指的是容器內的目錄。在docker run中經過-v參數指定宿主機目錄:容器目錄的方式在dockerfile中是行不通的。這是由於dockerfile是以建立容器的模板做用而存在,可能會應用於不一樣的宿主機甚至不一樣的系統平臺,不一樣的平臺路徑格式也不相同。雖然不能指定宿主機中的目錄,不過,經過dockerfile建立愛你的數據卷都默認存在於/var/lib/docker/volumes/目錄下。下面咱們使用dockerfile建立數據卷,首先建立一個目錄,而後進入該目錄,在目錄內建立一個名爲dockerfile的文件,寫入一下內容:

FROM ubuntu
VOLUME ["/dataVolume1","/dataVolume2"]
CMD echo "Success to build volume"
CMD /bin/bash

在命令行下使用docker build命令建立鏡像:

$ docker build -t docker_volume .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM ubuntu
---> 7698f282e524
Step 2/4 : VOLUME ["/dataVolume1","/dataVolume2"]
---> Running in 42cee5bb0fc8
Removing intermediate container 42cee5bb0fc8
---> 96e9ce4e0eae
Step 3/4 : CMD echo "Success to build volume"
---> Running in 04fbe86e45cc
Removing intermediate container 04fbe86e45cc
---> f66a3493edc6
Step 4/4 : CMD /bin/bash
---> Running in 6f39c6dbb2d8
Removing intermediate container 6f39c6dbb2d8
---> 42bd7a7b12ff
Successfully built 42bd7a7b12ff
Successfully tagged docker_volume:latest

使用鏡像建立容器,而後進入容器查看是否有數據卷:

$ docker run -it 42bd7a7b12ff
root@266fdc2a5ad7:/# ll
total 80
drwxr-xr-x 1 root root 4096 Jun 17 13:26 ./
drwxr-xr-x 1 root root 4096 Jun 17 13:26 ../
-rwxr-xr-x 1 root root 0 Jun 17 13:26 .dockerenv*
drwxr-xr-x 2 root root 4096 May 15 14:07 bin/
drwxr-xr-x 2 root root 4096 Apr 24 2018 boot/
drwxr-xr-x 2 root root 4096 Jun 17 13:26 dataVolume1/
drwxr-xr-x 2 root root 4096 Jun 17 13:26 dataVolume2/

能夠看到,dataVolume1和dataVolume2兩個目錄果真是存在的。

咱們可使用docker inspect命令查看詳細信息:

$ docker inspect 266fdc2a5ad7
……
"Mounts": [
{
"Type": "volume",
"Name": "d2d2f7ee61c5f8db0b8ccc2ff08f121079c3f16c5e48cd99e1d65538ef44e389",
"Source": "/var/lib/docker/volumes/d2d2f7ee61c5f8db0b8ccc2ff08f121079c3f16c5e48cd99e1d65538ef44e389/_data",
"Destination": "/dataVolume1",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "eacb8887be7cee176c1901f0e61ab7d51998a11366cc5a4b5fd3313c79f6ba48",
"Source": "/var/lib/docker/volumes/eacb8887be7cee176c1901f0e61ab7d51998a11366cc5a4b5fd3313c79f6ba48/_data",
"Destination": "/dataVolume2",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
……

查詢出來的信息太多,上面只貼出了數據卷的掛載信息,Name是指數據卷的名稱,是自動生成的,Source是宿主機內的數據卷目錄,使用超級管理員權限打開/var/lib/docker/volumes/目錄能夠查看到,Destination是容器內的數據卷目錄。

dockerfile建立的數據卷性質與docker run -v命令行建立的是同樣的,這裏再也不多說。

3 數據卷容器

有時候,咱們有一些常常性發生變化的數據須要在多個容器之間進行共享,這時候,一個更好的選擇就是使用數據卷容器。所謂數據卷容器,從名字上也能夠看出也是一個容器,不過,這個容器是專門用來爲其餘容器提供數據捲進行掛在的。

咱們先建立一個帶數據卷的容器:

$ docker run -it -v /dbdata --name dbContainer ubuntu

而後用這個容器爲其餘容器提供數據卷。使用--volumes-from來掛載數據卷容器。以下所示:

~/docker_test$ docker run -it --volumes-from dbContainer --name c1 ubuntu
root@50ce83189ae3:/# ll
total 76
……
drwxr-xr-x 2 root root 4096 Jun 17 14:57 dbdata/
……

能夠看到,容器內出現了dbdata目錄,這就是經過--volumes-from參數與dbContainer容器掛載而來的。

數據卷容器能夠同時被多個容器掛載,甚至,已經掛載了數據卷的容器能夠級聯掛載別的容器。

$ docker run -it --volumes-from c1 --name c2 ubuntu
root@97e7dae4a04b:/# ll
total 76
……
drwxr-xr-x 2 root root 4096 Jun 17 14:57 dbdata/
……

可見,dbContainer、c一、c2逐級掛載,這是沒有問題的,並且,--volumes-from參數所掛載的數據卷的容器並不須要保持運行狀態,也便是說dbContainer、c一、c2任意一個容器退出也不會影響其餘兩個容器。

另外,刪除掛載的容器(dbContainer、c一、c2任意一個),數據卷並不會被自動刪除,若是要刪除數據卷,須要在刪除最後一個掛載着這個數據卷的時候顯式的使用docker rm -v參數來同時刪除容器。

相關文章
相關標籤/搜索