1. 程式人生 > >docker 之 卷的概念

docker 之 卷的概念

lba 獨立 數據共享 etc 改變 dev 持久 docker容器 準備

1 概述

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

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

如果運行的容器修改了現有的一個已經存在的文件,那該文件就會從讀寫層下面的只讀層復制到讀寫層,該文件的只讀版本依然存在,只是已經被讀寫層中該文件的副本所隱藏,為“寫時復制”機制

聯合掛載解決了鏡像分發問題,但是導致性能損耗,

關閉並重啟容器,其數據不受影響;但刪除Docker容器,則其更改將會全部丟失

存在以下三個問題

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

.容器間數據共享不便

.刪除容器其數據會丟失

解決方案:使用“卷(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 <[email protected]>" -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,因為可能存在多個卷掛載的情況

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


docker 之 卷的概念