docker 之 卷的概念
容器的數據存放在最上層的讀寫層。
Docker鏡像由多個只讀層疊加而成,啟動容器時,docker會加載只讀鏡像層並在鏡像棧頂部添加一個讀寫層
如果運行的容器修改了現有的一個已經存在的文件,那該文件就會從讀寫層下面的只讀層復制到讀寫層,該文件的只讀版本依然存在,只是已經被讀寫層中該文件的副本所隱藏,為“寫時復制”機制
聯合掛載解決了鏡像分發問題,但是導致性能損耗,
關閉並重啟容器,其數據不受影響;但刪除Docker容器,則其更改將會全部丟失
存在以下三個問題
.存儲於聯合文件系統中,不易於宿主機訪問;
.容器間數據共享不便
.刪除容器其數據會丟失
解決方案:使用“卷(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 <[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 之 卷的概念