看誰(shuí)還不懂 Docker 數(shù)據(jù)卷 !
點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)??
大家好,我是小哈~
今天分享的主題是 Docker 數(shù)據(jù)卷。本文首發(fā)至犬小哈教程網(wǎng):www.quanxiaoha.com
一、什么是數(shù)據(jù)卷?
簡(jiǎn)單來(lái)說(shuō),數(shù)據(jù)卷是一個(gè)可供一個(gè)或多個(gè)容器使用的特殊目錄,用于持久化數(shù)據(jù)以及共享容器間的數(shù)據(jù),它以正常的文件或目錄的形式存在于宿主機(jī)上。 另外,其生命周期獨(dú)立于容器的生命周期,即當(dāng)你刪除容器時(shí),數(shù)據(jù)卷并不會(huì)被刪除。
二、為什么需要數(shù)據(jù)卷?
Docker 鏡像由多個(gè)文件系統(tǒng)(只讀層)疊加而成。Docker 會(huì)加載只讀鏡像層,并在鏡像棧頂部添加一個(gè)讀寫層。當(dāng)運(yùn)行容器后,如果修改了某個(gè)已存在的文件,那么該文件將會(huì)從下面的只讀層復(fù)制到上面的讀寫層,同時(shí),該文件在只讀層中仍然存在。當(dāng)我們刪除 Docker 容器,并通過(guò)鏡像重新啟動(dòng)容器時(shí),之前的更改的文件將會(huì)丟失。
那么,要如何解決數(shù)據(jù)持久化的問(wèn)題呢?于是,Docker 提出了 Volume 數(shù)據(jù)卷的概念。
三、數(shù)據(jù)卷特性
數(shù)據(jù)卷可以在容器之間共享和重用; 對(duì)數(shù)據(jù)卷的修改會(huì)立刻生效; 更新數(shù)據(jù)卷不會(huì)影響鏡像; 數(shù)據(jù)卷默認(rèn)一直存在,即使容器被刪除;
四、掛載數(shù)據(jù)卷
Docker 提供了 3 種不同的方式將數(shù)據(jù)從宿主機(jī)掛載到容器中。

4.1 volume (最常用的方式)
volume : Docker 管理宿主機(jī)文件系統(tǒng)的一部分,默認(rèn)位于 /var/lib/docker/volumes 目錄下, 也是最常用的方式。

看上圖,所有的 Docker 容器數(shù)據(jù)都保存在 /var/lib/docker/volumes 目錄下。若容器運(yùn)行時(shí)未指定數(shù)據(jù)卷, Docker 創(chuàng)建容器時(shí)會(huì)使用默認(rèn)的匿名卷(名稱為一堆很長(zhǎng)的 ID)。
注意:Mac 系統(tǒng)中, Docker 是基于虛擬機(jī)的 ,必須登錄到虛擬機(jī)里面,登錄后在目錄
/var/lib/docker/volumes/下即可找到數(shù)據(jù)卷。
4.2 bind mount(比較常用的方式)
bind mount: 意為可以存儲(chǔ)在宿主機(jī)中的任意位置。需要注意的是,bind mount 在不同的宿主機(jī)系統(tǒng)時(shí)不可移植的,比如 Windows 和 Linux 的目錄結(jié)構(gòu)是不一樣的,bind mount 所指向的 host 目錄也不一樣。這也是為什么 bind mount 不能出現(xiàn)在 Dockerfile 中的原因所在,因?yàn)檫@樣 Dockerfile 就不可移植了。
4.3 tmpfs mount (一般不用這種方式)
tmpfs mount : 掛載存儲(chǔ)在宿主機(jī)的內(nèi)存中,而不會(huì)寫入宿主機(jī)的文件系統(tǒng),一般不用此種方式。
五、Volume 使用
5.1 創(chuàng)建一個(gè)數(shù)據(jù)卷
執(zhí)行如下命令創(chuàng)建數(shù)據(jù)卷:
docker volume create test-vol

5.2 查看所有的數(shù)據(jù)卷
docker volume ls

5.3 查看數(shù)據(jù)卷信息
執(zhí)行如下命令,可以查看指定的數(shù)據(jù)卷信息:
# 查看數(shù)據(jù)卷名為 test-vol 的信息
docker volume inspect test-vol

5.4 運(yùn)行容器時(shí)掛載數(shù)據(jù)卷
數(shù)據(jù)卷 test-vol創(chuàng)建成功后,我們運(yùn)行一個(gè) Nginx 容器,并嘗試掛載該數(shù)據(jù)卷,掛載命令支持兩種:
-v
docker run -d -it --name=test-nginx -p 8011:80 -v test-vol:/usr/share/nginx/html nginx:1.13.12
參數(shù)說(shuō)明:
-d: 后臺(tái)運(yùn)行容器;--name=test-nginx: 指定容器名為 test-nginx;-p 8011:80: 將容器的 80 端口掛載到宿主機(jī)的 8011 端口;-v test-vol:/usr/share/nginx/html: 將test-vol數(shù)據(jù)卷掛載到容器中的 /usr/share/nginx/html 目錄上;
--mount
docker run -d -it --name=test-nginx -p 8011:80 --mount source=test-vol,target=/usr/share/nginx/html nginx:1.13.12
參數(shù)說(shuō)明:
--mount source=test-vol,target=/usr/share/nginx/html: 將test-vol數(shù)據(jù)卷掛載到容器中的 /usr/share/nginx/html 目錄上;
-v 和 --mount 有什么區(qū)別?
都是掛載命令,使用 -v 掛載時(shí),如果宿主機(jī)上沒(méi)有指定文件不會(huì)報(bào)錯(cuò),會(huì)自動(dòng)創(chuàng)建指定文件;當(dāng)使用 --mount時(shí),如果宿主機(jī)中沒(méi)有這個(gè)文件會(huì)報(bào)錯(cuò)找不到指定文件,不會(huì)自動(dòng)創(chuàng)建指定文件。
容器運(yùn)行成功后,進(jìn)入到 /var/lib/docker/volumes 目錄下,驗(yàn)證數(shù)據(jù)是否掛載成功:

可以看到已經(jīng)有了 50x.html 、 index.html 兩個(gè) Nginx 頁(yè)面相關(guān)數(shù)據(jù),說(shuō)明數(shù)據(jù)卷掛載成功了。掛載成功后,我們不論是修改 /var/lib/docker/volumes 下的數(shù)據(jù),還是進(jìn)入到容器中修改 /usr/share/nginx/html 下的數(shù)據(jù),都會(huì)同步修改對(duì)應(yīng)的掛載目錄,類似前端開(kāi)發(fā)中雙向綁定的作用。
下面,我們停止并刪除剛剛運(yùn)行的 Nginx 容器, 看看數(shù)據(jù)卷中的數(shù)據(jù)是否會(huì)跟著被刪除:

可以發(fā)現(xiàn)數(shù)據(jù)卷相關(guān)數(shù)據(jù)都還在,表明數(shù)據(jù)卷的生命周期獨(dú)立于容器。另外,若下次再創(chuàng)建 Nginx 容器,還可以復(fù)用這個(gè)數(shù)據(jù)卷,復(fù)用性以及擴(kuò)張性都非常不錯(cuò)。
刪除數(shù)據(jù)卷
由于數(shù)據(jù)卷的生命期獨(dú)立于容器,想要?jiǎng)h除數(shù)據(jù)卷,就需要我們手動(dòng)來(lái)操作, 執(zhí)行命令如下:
docker volume rm test-vol
如果你需要在刪除容器的同時(shí)移除數(shù)據(jù)卷,請(qǐng)使用
docker rm -v命令。對(duì)于那些沒(méi)有被使用的數(shù)據(jù)卷,可能會(huì)占用較多的磁盤空間,你可以通過(guò)如下命令統(tǒng)一刪除:
docker volume prune
bind mount 使用
通過(guò) bind mount 模式可以掛載到宿主機(jī)的任意位置,示例如下:
docker run -d -it --name=test-nginx -p 8011:80 -v /docker/nginx1:/usr/share/nginx/html nginx:1.13.12
參數(shù)說(shuō)明:
-v /docker/nginx1:/usr/share/nginx/html: 將宿主機(jī)中的/docker/nginx1目錄掛載到容器中的/usr/share/nginx/html目錄;
容器運(yùn)行成功后,進(jìn)入容器中:
docker exec -it test-nginx /bin/bash

從上圖可以看到,與 volume 不同,bind mount 這種方式會(huì)隱藏目錄中的內(nèi)容(非空情況下),這里的 /usr/share/nginx/html 目錄下的 html 文件被隱藏了,所以我們看不到。
但是,我們可以將宿主機(jī)中該目錄中的文件立刻掛載到容器中,下面驗(yàn)證一下:
新建一個(gè) index.html:

再次進(jìn)入容器,查看掛載目錄內(nèi)容:

數(shù)據(jù)卷容器
如果你有一些需要持續(xù)更新的數(shù)據(jù)需要在容器之間共享,最佳實(shí)踐是創(chuàng)建數(shù)據(jù)卷容器。數(shù)據(jù)卷容器,其實(shí)就是一個(gè)正常的 Docker 容器,專門用于提供數(shù)據(jù)卷供其他容器掛載的。
創(chuàng)建數(shù)據(jù)卷容器
運(yùn)行一個(gè)容器,并創(chuàng)建一個(gè)名為 dbdata 的數(shù)據(jù)卷:
docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres

容器運(yùn)行成功后,會(huì)發(fā)現(xiàn)該數(shù)據(jù)卷容器處于停止運(yùn)行狀態(tài),這是因?yàn)閿?shù)據(jù)卷容器并不需要處于運(yùn)行狀態(tài),只需用于提供數(shù)據(jù)卷掛載即可。
掛載數(shù)據(jù)卷
--volumes-from 命令支持從另一個(gè)容器掛載容器中已創(chuàng)建好的數(shù)據(jù)卷。
docker run -d --volumes-from dbdata --name db1 training/postgres
docker run -d --volumes-from dbdata --name db2 training/postgres
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7348cb189292 training/postgres "/docker-entrypoint. 11 seconds ago Up 10 seconds 5432/tcp db2
a262c79688e8 training/postgres "/docker-entrypoint. 33 seconds ago Up 32 seconds 5432/tcp db1
還可以使用多個(gè) --volumes-from 參數(shù)來(lái)從多個(gè)容器掛載多個(gè)數(shù)據(jù)卷。也可以從其他已經(jīng)掛載了數(shù)據(jù)卷的容器來(lái)掛載數(shù)據(jù)卷。
如果刪除了掛載的容器(包括 dbdata、db1 和 db2),數(shù)據(jù)卷并不會(huì)被自動(dòng)刪除。如果想要?jiǎng)h除一個(gè)數(shù)據(jù)卷,必須在刪除最后一個(gè)還掛載著它的容器時(shí)使用 docker rm -v 命令來(lái)指定同時(shí)刪除關(guān)聯(lián)的容器。
使用數(shù)據(jù)卷容器備份、恢復(fù)、遷移數(shù)據(jù)卷
本小節(jié)中,我們將學(xué)習(xí)如何對(duì)數(shù)據(jù)卷容器中的數(shù)據(jù)進(jìn)行進(jìn)行備份、恢復(fù)和遷移。
備份
首先使用 --volumes-from 命令創(chuàng)建一個(gè)加載 dbdata 的容器卷容器,并將宿主機(jī)當(dāng)前目錄掛載到容器的 /backup 目錄,命令如下:
$ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
容器啟動(dòng)后,使用了 tar 命令來(lái)將 dbdata 數(shù)據(jù)卷備份為容器中 /backup/backup.tar 文件,因?yàn)閽燧d了的關(guān)系,宿主機(jī)的當(dāng)前目錄下也會(huì)生成 backup.tar 備份文件。
恢復(fù)/遷移
如果要恢復(fù)數(shù)據(jù)到一個(gè)容器,首先創(chuàng)建一個(gè)帶有空數(shù)據(jù)卷的容器 dbdata2。
$ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
然后創(chuàng)建另一個(gè)容器,掛載 dbdata2 容器卷中的數(shù)據(jù)卷,并使用 untar 解壓備份文件到掛載的容器卷中。
$ sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf
/backup/backup.tar
為了查看/驗(yàn)證恢復(fù)的數(shù)據(jù),可以再啟動(dòng)一個(gè)容器掛載同樣的容器卷來(lái)查看:
$ sudo docker run --volumes-from dbdata2 busybox /bin/ls /dbdata
1. CTO強(qiáng)烈禁止使用Calendar,那用啥?
2. 看了我的mybatis-plus用法,同事也開(kāi)始悄悄模仿了
3. 九種方式,教你讀取 resources 目錄下的文件路徑
4. 大批程序員被勸退!
最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
PS:因公眾號(hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過(guò)內(nèi)容,記得讀完點(diǎn)一下“在看”,加個(gè)“星標(biāo)”,這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。
點(diǎn)“在看”支持小哈呀,謝謝啦??

