容器中的數(shù)據(jù)與Host相互獨立,隨著容器的釋放(刪除),這些數(shù)據(jù)也將丟失.
為了避免這個問題,Docker提供了數(shù)據(jù)卷(Volume)這個數(shù)據(jù)持久化工具.
持久化后的數(shù)據(jù),不會隨著容易刪除而丟失.
概述
試想這樣一個場景,幾年前我創(chuàng)建了一個mysql5.5的容器,幾年后由于業(yè)務變動,需要升級到mysql5.6,這個時候需要登陸到容器里面,把mysql的表文件復制下來,再想辦法遷移到新的mysql服務中.
這個手動復制的過程很容易出現(xiàn)意外,萬一不粗心大意,沒有復制data就刪除了容器,那差不多可以跑路了,否則就等著全村吃席吧.
好在Docker提供了bind mount和volume兩種方式來做數(shù)據(jù)持久化,先準備個mysql鏡像準備演示.
docker pull mysql:5.6
bind mount
bind mount是將host上的一個目錄mount到容器中,類似于一個共享文件夾.
要bind mount一個目錄到容器,需要在創(chuàng)建容器時使用-v 本地目錄:容器目錄參數(shù)指定
docker run -v /Users/zhangsan/opt:/opt ......
上述例子將本地/Users/zhangsan/opt目錄掛在到容器的/opt目錄. 登陸容器,
docker exec -it mysql_test_volume /bin/bash
echo Hello,World >> index.html
exit
此時本地的/Users/zhangsan/opt目錄就會出現(xiàn)剛才創(chuàng)建index.html.
反之,如果在本地新增文件index2.html,容器內也會出現(xiàn)這個文件.
使用bind mount需要注意以下幾點:
-
host路徑必須為全路徑,否則回和volume混淆 - 如果
host目錄不存在,docker會自動創(chuàng)建該目錄 - 如果容器目錄不存在,
docker會自動創(chuàng)建該目錄 - 如果容器目錄已有數(shù)據(jù),那么
docker會將其覆蓋掉
就上面那個場景,如果使用了 bind mount,此時只需要新起一個5.6版本的容器,將目錄mount到新地址即可.
docker run -v /Users/zhangsan/opt:/opt --name mysql_test_volume -d -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:5.6
由于bind mount本質是個共享文件夾,因而依賴于系統(tǒng)文件系統(tǒng),不同系統(tǒng)間無法移植,
windows的NTFS文件系統(tǒng)就無法與linux常用的ext3/4兼容,windows目錄為\Users\zhangsan\...格式,
而ext4文件系統(tǒng)目錄路徑為/usr/...
volume
volume是容器上的一個或者多個目錄,此目錄可以繞過文件系統(tǒng),與宿主機上的某目錄綁定.
volume于容器化初始化之時即會創(chuàng)建,可以在不同host上移植,卷中的數(shù)據(jù)會在build image期間完成復制.
- 數(shù)據(jù)卷可以在容器之間共享和重用
- 對數(shù)據(jù)卷的更改是直接進行的
- 更新鏡像時,不包括對數(shù)據(jù)卷的更改
- 即使刪除容器本身,數(shù)據(jù)卷也會保持
使用docker volume create volume_name來創(chuàng)建一個卷
docker volume create test
將test掛在到容器上
docker run -v test:/opt --name mysql_test_volume -d -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:5.6
查看所有卷,使用
docker volume ls
查看一個卷信息,使用
docker volume inspect volume_name

刪除未使用的卷
docker volume prune
刪除一個卷
docker volume rm volume_name
與bind mount不同的是,
- 如果
volume是空的而容器中的目錄有內容,那么docker會將container目錄中的內容拷貝到volume中 - 但是如果
volume中已經有內容,則會將container中的目錄覆蓋 - Mac系統(tǒng)的
docker Desktop實際上是構建在虛擬機上的,其volume在虛擬機的var/lib/docker/volume中,本機上不存在這個路徑.
volume遷移
最2的方式,登陸host的/var/lib/docker/volume目錄找到對應的volume,打包帶走,在新host的volume中解壓.
上面注部分提到過volume的特點,可以利用這點來進行遷移,假設有一個卷test需要遷移,步驟如下
1.下載一個鏡像,越小越好,比如(alpine)
2.通過這個鏡像創(chuàng)建容器A,掛在test,由于容器內容為空,test中的數(shù)據(jù)會被復制到容器目錄中
3.打包這個容器A打包成鏡像image-A,push或者本地快照
4.新機器上新建同名volume,然后pull或者import鏡像image-A
5.通過鏡像image-A啟動容器B,掛載卷test,由于test是空的而容器目錄有內容,docker會將container目錄中的內容拷貝到volume中.
6.刪除鏡像image-A,容器A,容器B,由于數(shù)據(jù)卷不會被刪除,因而就完成了遷移,可以給新的容器使用.
這樣volume就隨著容器遷移到新的host上了