生產(chǎn)環(huán)境中使用docker的過程中,往往需要對數(shù)據(jù)進(jìn)行持久化,或者需要在多個(gè)容器之間進(jìn)行數(shù)據(jù)共享,這必然涉及容器的數(shù)據(jù)管理操作。
容器中管理數(shù)據(jù)主要有兩種方式:
- 數(shù)據(jù)卷(Data Volumes): 容器內(nèi)數(shù)據(jù)直接映射到本地主機(jī)環(huán)境;
- 數(shù)據(jù)卷容器(Data Volume Containers): 使用特定容器維護(hù)數(shù)據(jù)卷。
本篇文章首先介紹如何在容器內(nèi)創(chuàng)建數(shù)據(jù)卷,并且把本地的目錄或文件掛載到容器內(nèi)的數(shù)據(jù)卷中。接下來,會(huì)介紹如何使用數(shù)據(jù)卷容器在容器和主機(jī)、容器和容器之間共享數(shù)據(jù),并實(shí)現(xiàn)數(shù)據(jù)的備份和恢復(fù)。
6.1 數(shù)據(jù)卷
數(shù)據(jù)卷是一個(gè)可供容器使用的特殊目錄,它將主機(jī)操作系統(tǒng)目錄直接映射進(jìn)容器,類似Linux中的mount操作。
數(shù)據(jù)卷可以提供很多有用的特性,如下所示:
- 數(shù)據(jù)卷可以在容器之間共享和重用,容器之間傳遞數(shù)據(jù)將變得高效方便;
- 對數(shù)據(jù)卷內(nèi)數(shù)據(jù)的修改會(huì)立馬生效,無論是容器內(nèi)操作還是本地操作;
- 對數(shù)據(jù)卷的更新不會(huì)影響鏡像,解耦了應(yīng)用和數(shù)據(jù);
- 卷會(huì)一直存在,知道沒有容器使用,可以安全的卸載它。
1.在容器內(nèi)創(chuàng)建一個(gè)數(shù)據(jù)卷
在用docker run命令的時(shí)候,使用-v標(biāo)記可以在容器內(nèi)創(chuàng)建一個(gè)數(shù)據(jù)卷。多次重復(fù)-v標(biāo)記可以創(chuàng)建多個(gè)數(shù)據(jù)卷。
下面 使用webserver鏡像創(chuàng)建一個(gè)web容器,并創(chuàng)建一個(gè)數(shù)據(jù)卷掛載到容器的/webapp目錄。
[root@private_vpn ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v0.21 e230d26d7671 2 hours ago 967.9 MB
centos6.8 0.21 7e48bfa0489e 30 hours ago 1.052 GB
[root@private_vpn ~]# docker run -itd -p 80:80 --name web -v /tmp/webapp:/webapp webserver:v0.21 /bin/bash
71cf8102d33c8e2a5ddfb69ed28bf8743ee4c1dbc27c9c6fd0a69c1d97b74d58
[root@private_vpn ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
71cf8102d33c webserver:v0.21 "/bin/bash" 4 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp web
[root@private_vpn ~]#
[root@private_vpn ~]# ls -l /tmp/webapp/
total 0
[root@private_vpn ~]# docker exec -ti 71 /bin/bash
[root@71cf8102d33c /]# ls -l /webapp
total 0
[root@71cf8102d33c /]# cat /tmp/test.txt #容器講解那篇文章創(chuàng)建的測試文件
test
命令:docker run -itd -p 80:80 --name web -v /tmp/webapp:/webapp webserver:v0.21 /bin/bash
使用-v標(biāo)記指定掛載一個(gè)本地的已有目錄到容器中去作為數(shù)據(jù)卷(推薦方式)
上面的命令加載主機(jī)的/tmp/webapp目錄到容器的/webapp目錄。
注意:本地路徑必須是絕對路徑且存在,如果目錄不存在docker容器,則會(huì)自動(dòng)創(chuàng)建。
-p: 指定端口映射,本地到docker容器。
--name: 指定容器名字
在主機(jī)/tmp/webapp目錄下創(chuàng)建文件并寫入內(nèi)容:
[root@private_vpn ~]# cd /tmp/webapp/
[root@private_vpn webapp]# ls
[root@private_vpn webapp]# echo "This is a docker web test page" >> index.html
[root@private_vpn webapp]# cat index.html
This is a docker web test page
docker容器內(nèi)檢查數(shù)據(jù)是否已共享:
[root@71cf8102d33c webapp]# cat index.html
This is a docker web test page
數(shù)據(jù)已共享,在主機(jī)和容器之間。
然后再訪問試試看(當(dāng)然我的此容器內(nèi)已經(jīng)安裝好了nginx服務(wù),根據(jù)需求自己修改配置):

已經(jīng)成功。
也可以先創(chuàng)建數(shù)據(jù)卷,然后在啟動(dòng)容器的時(shí)候掛載數(shù)據(jù)卷
docker volume create my-vol
同樣可以通過inspect命令查看數(shù)據(jù)卷詳細(xì)信息
可以看到在/data/docker/volumes/目錄下創(chuàng)建一個(gè)數(shù)據(jù)卷my-vol(我之前修改了Docker Root Dir的目錄為/data/docker/)
[root@test ~]# docker volume create my-vol
my-vol
[root@test ~]# docker volume ls
DRIVER VOLUME NAME
local my-vol
[root@test ~]# docker volume inspect my-vol
[
{
"CreatedAt": "2020-01-08T13:39:54+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/data/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
啟動(dòng)一個(gè)掛載數(shù)據(jù)卷的容器:在用docker run命令的時(shí)候,使用--mount或者-v標(biāo)記來將數(shù)據(jù)卷掛載到容器里。下面創(chuàng)建一個(gè)名為本web的容器,并加載一個(gè)數(shù)據(jù)卷到容器的/usr/share/nginx/html目錄。
docker run -d -p 8080:80 --name web -v my-vol:/usr/share/nginx/html nginx
[root@test ~]# docker run -d -p 8080:80 --name web -v my-vol:/usr/share/nginx/html nginx
f1ae7c82566a0bdb60931a8403b4ff6f72fd09673d0e586dac3ac11c49dc22ea
[root@test ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f1ae7c82566a nginx "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp web
運(yùn)行完成后,可以查看數(shù)據(jù)卷目錄下面已經(jīng)有文件了。
[root@test ~]# ls -l /data/docker/volumes/my-vol/_data/
total 8
-rw-r--r-- 1 root root 494 Nov 19 20:50 50x.html
-rw-r--r-- 1 root root 612 Nov 19 20:50 index.html
添加文件并測試訪問
[root@test ~]# cd /data/docker/volumes/my-vol/_data/
[root@test _data]# vim 1.html
[root@test _data]# cat 1.html
my-vol haha
[root@test _data]# curl localhost:8080/1.html
my-vol haha
數(shù)據(jù)卷時(shí)被設(shè)計(jì)用來持久化數(shù)據(jù)的,它的生命周期獨(dú)立于容器,Docker不會(huì)在容器被刪除后自動(dòng)刪除數(shù)據(jù)卷,并且也不存在垃圾回收這樣的機(jī)制來處理沒有任何容器引用的數(shù)據(jù)卷。如果需要在刪除容器的同時(shí)移除數(shù)據(jù)卷,可以在刪除容器的時(shí)候使用docker rm -v這個(gè)命令。無主的數(shù)據(jù)卷可能會(huì)占據(jù)很多存儲(chǔ)空間,需要清理請使用docker volume prune命令。
掛載權(quán)限
默認(rèn)掛載的路徑權(quán)限為讀寫。如果指定為只讀可以用:ro,如:-v /tmp:/usr/tmp:ro。
– 容器目錄不可以為相對路徑
– 宿主機(jī)目錄如果不存在,則會(huì)自動(dòng)生成
– 掛載宿主機(jī)已存在目錄后,在容器內(nèi)對其進(jìn)行操作,報(bào)“Permission denied”??赏ㄟ^兩種方式解決:
* 1> 關(guān)閉selinux。
臨時(shí)關(guān)閉:`# setenforce 0`
永久關(guān)閉:修改`/etc/sysconfig/selinux`文件,將 SELINUX 的值設(shè)置為disabled。
* 2> 以特權(quán)方式啟動(dòng)容器
指定`--privileged`參數(shù),如:
`# docker run -it --privileged=true -v /test:/soft centos /bin/bash`