1 概述
html
容器的數據存放在最上層的讀寫層。docker
Docker鏡像由多個只讀層疊加而成,啓動容器時,docker會加載只讀鏡像層並在鏡像棧頂部添加一個讀寫層json
若是運行的容器修改了現有的一個已經存在的文件,那該文件就會從讀寫層下面的只讀層複製到讀寫層,該文件的只讀版本依然存在,只是已經被讀寫層中該文件的副本所隱藏,爲「寫時複製」機制bash
聯合掛載解決了鏡像分發問題,可是致使性能損耗,架構
關閉並重啓容器,其數據不受影響;但刪除Docker容器,則其更改將會所有丟失 ide
存在如下三個問題 性能
.存儲於聯合文件系統中,不易於宿主機訪問; spa
.容器間數據共享不便htm
.刪除容器其數據會丟失 進程
解決方案:使用「卷(volume)」 ,卷是容器上的一個或者多個「目錄」,此類目錄可繞過聯合文件系統,與宿主機的某個目錄「綁定」,使得數據脫離容器而存在,容器刪除後,數據依然存在。
每個掛載點稱爲卷,這裏的掛載是用來掛載目錄的(bind,目錄掛目錄)。
一個卷用來綁定一個目錄,一個容器能夠定義多個卷
卷關聯宿主機上的某一路徑,卷和聯合掛載不同,優於聯合掛載
卷實現了數據的持久化
卷爲docker提供了獨立於容器的數據管理機制
.能夠把 「鏡像 」想像成靜態文件,例如 「程序 」,把卷類比爲動態內容,例如 「數據 」;因而,鏡像能夠重用,而卷能夠共享;
.卷實現了 「程序 (鏡像 )」和「數據 (卷)」分離,以及 「程序 (鏡像 )」和「製做鏡像的主機 」分離,用戶製做鏡像時無須再考慮鏡像運行的容器所在的主機的環境;
2 卷的類型
卷有兩種類型:
Docker有兩種類型的卷,每種類型都在容器中存在一個掛載點,但其在宿主機上的位置有所不一樣;
1:綁定掛載卷:由用戶指定宿主機的路徑,須要人工建立好宿主機的目錄。
2:docker管理的卷: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,由於可能存在多個卷掛載的狀況
注意,刪除容器默認不會刪除相關的卷 ,生產環境,建議不要刪除卷,由於一旦把卷刪除,相關數據也會丟失。