容器就至關於一個簡易的操做系統,咱們在上面部署咱們的環境,不可避免地產生一些數據,可是,可能因爲斷電等等緣由,容器退出了,那麼以前容器中的數據就不符存在,則每每不是咱們想要的,更多的,咱們是但願數據可以持久保存到硬盤中,這就須要用到數據卷。docker
數據卷是指一種目錄或者說文件,其存在於一個或者多個容器中,由docker掛載到容器,但不屬於UFS(Union File System,聯合文件系統),所以可以繞開UFS提供一些用於持續存儲或共享數據的特性。ubuntu
數據卷的設計目的就是爲了實現數據的持久化,徹底獨立於容器的生存週期,所以docker不會在容器刪除時刪除其掛載的數據卷。除此之外,數據卷還能夠實現容器間的數據繼承和共享。在使用上,數據卷的特色:bash
下面就開始來研究一下添加數據卷。添加數據卷有兩種方法,第一種是經過命令直接添加,第二種是經過dockerfile添加。ide
在上一篇博文中,提到過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 ../
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
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命令行建立的是同樣的,這裏再也不多說。
有時候,咱們有一些常常性發生變化的數據須要在多個容器之間進行共享,這時候,一個更好的選擇就是使用數據卷容器。所謂數據卷容器,從名字上也能夠看出也是一個容器,不過,這個容器是專門用來爲其餘容器提供數據捲進行掛在的。
咱們先建立一個帶數據卷的容器:
$ 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參數來同時刪除容器。