docker 之 卷的概念

1  概述
html

容器的數據存放在最上層的讀寫層。docker

Docker鏡像由多個只讀層疊加而成,啓動容器時,docker會加載只讀鏡像層並在鏡像棧頂部添加一個讀寫層json

若是運行的容器修改了現有的一個已經存在的文件,那該文件就會從讀寫層下面的只讀層複製到讀寫層,該文件的只讀版本依然存在,只是已經被讀寫層中該文件的副本所隱藏,爲「寫時複製」機制bash

聯合掛載解決了鏡像分發問題,可是致使性能損耗,架構

關閉並重啓容器,其數據不受影響;但刪除Docker容器,則其更改將會所有丟失 ide

存在如下三個問題 性能

.存儲於聯合文件系統中,不易於宿主機訪問; spa

.容器間數據共享不便htm

 .刪除容器其數據會丟失 進程

解決方案:使用「卷(volume)」 ,卷是容器上的一個或者多個「目錄」,此類目錄可繞過聯合文件系統,與宿主機的某個目錄「綁定」,使得數據脫離容器而存在,容器刪除後,數據依然存在。

每個掛載點稱爲卷,這裏的掛載是用來掛載目錄的(bind,目錄掛目錄)。

一個卷用來綁定一個目錄,一個容器能夠定義多個卷

卷關聯宿主機上的某一路徑,卷和聯合掛載不同,優於聯合掛載

卷實現了數據的持久化

卷爲docker提供了獨立於容器的數據管理機制 

.能夠把 「鏡像 」想像成靜態文件,例如 「程序 」,把卷類比爲動態內容,例如 「數據 」;因而,鏡像能夠重用,而卷能夠共享;

.卷實現了 「程序 (鏡像 )」和「數據 (卷)」分離,以及 「程序 (鏡像 )」和「製做鏡像的主機 」分離,用戶製做鏡像時無須再考慮鏡像運行的容器所在的主機的環境;

2  卷的類型

卷有兩種類型:

Docker有兩種類型的卷,每種類型都在容器中存在一個掛載點,但其在宿主機上的位置有所不一樣;

1:綁定掛載卷:由用戶指定宿主機的路徑,須要人工建立好宿主機的目錄。

2docker管理的卷:docker路徑不須要建立,docker進程會自動生成該路徑。

-f後是json格式的字典,查看分段格式的標誌

docker run命令使用-v選項便可使用Volume指定-v選項指定卷路徑,docker run命令使用-v選項便可使用Volume

2.1  docker管理的卷

例子以下:

 docker run -it  --name bbox1 –v /data busybox

查看 bbox1容器的卷、卷標識符及掛載的主機目錄

 docker inspect -f {{.Config.Volumes}}{{.Mounts}} bbox1

能夠用docker volume ls查看卷的名稱,在用docker volum inspect 卷名稱  來查看具體卷的信息

docker volume inspect  737432382e1292b2aa828f6e66f04721bf251dbeaa082b295f5bc08bf5ac6c60

找到的路徑爲本地的宿主機的路徑

這個方式,能夠直接在宿主機部署站點,直接把站點放到容器對應的目錄本地。

2.2  綁定掛載卷例子

格式

docker run -it -v HOSTDIR:VOLUMEDIR --name sunny02 busybox

如下HOSTDIR:VOLUMEDIR表示宿主機路徑:卷路徑,所以宿主機要先建立對應要掛載的目錄

如這裏建立宿主機目錄以下

 mkdir -pv /docker/data/volumes/sunny

啓動容器

docker run -it --name sunny02 -v /docker/data/volumes/sunny:/data/htdocs --rm busybox:1.27.2
docker inspect -f {{.Mounts}} sunny02

結果以下

[{bind  /docker/data/volumes/sunny /data/htdocs   true rprivate}]

bind表示綁定掛載卷

此時,路徑就是宿主機的/docker/data/volumes/sunny

若是路徑不須要管理就使用docker生成的卷,若是須要管理,就用綁定掛載卷

這裏,若是啓動的鏡像原本就存在/data/htdocs,即綁定掛載點自己有數據,新容器的掛載點啓動後,掛載目錄也是/data/htdocs,這個時候若是再次掛載到這個目錄,則原來鏡像裏的/data/htdocs數據不可見,已經被隱藏

例子以下

首先先製做一個鏡像

先啓動容器,並建立/data/htdocs/data/htdocs目錄下生成hello文件

[root@docker ~]# docker run -it --name sunny02 --rm busybox:1.27.2
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # mkdir /data/htdocs
mkdir: can't create directory '/data/htdocs': No such file or directory
/ # mkdir -p /data/htdocs
/ # cd /data/htdocs/
/data/htdocs # ls
/data/htdocs # echo "hello sunny" > hello
/data/htdocs # ls
hello
/data/htdocs #

環境準備好了,製做成鏡像

-a指明做者,-m備註,-p暫停容器時製做鏡像,即鏡像爲當前的容器狀態,testbox:sunnyv1爲當前標籤,-c改變容器默認的啓動命令

docker commit -a "sunny <sunny@ghbsunny.cn>" -m "sunny test" -p sunny02 testbox:sunnyv1

基於鏡像testbox:sunnyv1來啓動容器

先指定掛載點,此時容器有/data/htdocs這個目錄,且文件hello存在

[root@docker ~]# docker run -it --name sunny03 --rm testbox:sunnyv1
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cd /data/
/data # ls
htdocs
/data # cd htdocs/
/data/htdocs # ls
hello
/data/htdocs #

而後,指定掛載點,作對比區別

先建立宿主機目錄

mkdir -pv /docker/data/volumes/sunny02

指定掛載點後啓動容器

[root@docker ~]# docker run -it --name sunny02 -v /docker/data/volumes/sunny02:/data/htdocs --rm testbox:sunnyv1
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cd /data/
/data # ls
htdocs
/data # cd htdocs/
/data/htdocs # ls
/data/htdocs #

若是宿主機的掛載目錄/docker/data/volumes/sunny02有文件,則掛載後的容器依然是能夠看到/docker/data/volumes/sunny02的數據,可是原來鏡像 testbox:sunnyv1的/data/htdocs下的文件已經不可見,被隱藏了,和路徑掛載同樣。所以掛載時,要注意鏡像的路徑,不要隱藏掉鏡像須要使用的目錄數據

3  共享卷

有兩種方式能夠在容器間共享卷:

1..多個容器的卷使用同一個主機目錄,例如,如下兩個容器都使用宿主機的目錄 /docker/volumes/v1做爲數據盤

 docker run –it --name c1 -v /docker/volumes/v1:/data busybox
 docker run –it --name c2 -v /docker/volumes/v1:/data busybox

 .複製使用其它容器的卷,爲 docker run命令使用 --volumes-from選項

以下例子,先啓動了容器 bbox1,掛載本地 /docker/volumes/v1做爲卷目錄,再啓動容器bbox2,直接複製bbox1的卷做爲其容器的卷

docker run -it --name bbox1 -v /docker/volumes/v1:/data busybox
docker run -it --name bbox2  --volumes-from bbox1 busybox

複製卷,有一個好處是實現共享,有個場景爲,假設要掛載的卷不少,新生成的容器要一一掛載相同的宿主機目錄,很麻煩,並且掛載路徑可能出錯,所以能夠啓動一個容器,不跑程序,僅用於掛載卷,至關於模板,後期要使用這個卷的數據的容器,均可以經過  --volumes-from來直接掛載對應的卷,保證卷的數據和目錄都是一致的。這個容器

爲基礎架構容器,不作其餘操做,僅提供卷的複製

一個容器可使用多個卷,只須要用多個-v來指定便可

以下例子,同時指定兩個卷/docker/data/volumes/sunny02 /docker/data/volumes/sunny

[root@docker volumes]# docker run -it --name c6 -v /docker/data/volumes/sunny:/data/htdocs -v /docker/data/volumes/sunny02:/data/html busybox
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cd data
/data # ls
htdocs  html

這個也是爲何,複製卷的時候,要用參數 --volumes-from,由於可能存在多個卷掛載的狀況

注意,刪除容器默認不會刪除相關的卷 ,生產環境,建議不要刪除卷,由於一旦把卷刪除,相關數據也會丟失。

相關文章
相關標籤/搜索