赞
踩
这里先初步举个例子,用来理解什么是数据卷,什么是挂载,容器和宿主机又是如何进行关联:
启动redis容器,将名称改为redis,并为容器添加一个数据卷,这个数据卷在容器里的目录是/opt/data [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE redis latest 0a153379a539 5 days ago 83.4MB [root@localhost ~]# docker run --name redis -v /opt/data -tid 0a153379a539 /bin/bash 145fe5a93a6deaa76fd6c408d2b88ef2d685af48b03db3d0f64dd4a768b709a8 [root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 145fe5a93a6d 0a153379a539 "docker-entrypoint.s…" 14 seconds ago Up 13 seconds 6379/tcp redis 进入容器,在数据卷目录下创建文件 [root@localhost ~]# docker exec -it redis /bin/bash root@145fe5a93a6d:/data# cd /opt/data/ root@145fe5a93a6d:/opt/data# ls root@145fe5a93a6d:/opt/data# echo 123 > 123 root@145fe5a93a6d:/opt/data# echo 123123 > 123123 root@145fe5a93a6d:/opt/data# ls 123 123123 退出容器,在宿主机上查看对应上面的那个数据卷的目录路径,并修改其中一个文件 root@145fe5a93a6d:/opt/data# exit exit [root@localhost ~]# docker inspect redis|grep /var/lib/docker/volumes "Source": "/var/lib/docker/volumes/442f7aaf3f84b6b41d4cffc4e3e71a84ab1b89fe9dbe70b76e99f851ff1bf66e/_data", "Source": "/var/lib/docker/volumes/b11ec41d372b348ca953e6ba5eccfa88cd732d84f08524af8a3c40e1eb466362/_data", [root@localhost ~]# ls /var/lib/docker/volumes/442f7aaf3f84b6b41d4cffc4e3e71a84ab1b89fe9dbe70b76e99f851ff1bf66e/_data 123 123123 [root@localhost ~]# echo abcdef >> /var/lib/docker/volumes/442f7aaf3f84b6b41d4cffc4e3e71a84ab1b89fe9dbe70b76e99f851ff1bf66e/_data/123 进入容器,查看修改是否同步 [root@localhost ~]# docker exec -it redis /bin/bash root@145fe5a93a6d:/data# ls /opt/data/ 123 123123 root@145fe5a93a6d:/data# cat /opt/data/123 123 abcdef
可以直接挂载宿主机文件或目录到容器里,可以理解为目录映射,这样就可以让所有的容器共享宿主机数据,从而只需要改变宿主机的数据源就能够影响到所有的容器数据,或者当容器意外删除的时候,宿主机的数据仍然有一份,便于容灾。
挂载命令:
-v hostFile:containerFile
- hostFile表示宿主机的目录或文件,需要提前存在的
- containerFile表示容器的目录或文件,运行容器时会自动创建
- 容器数据卷的权限默认是可读可写权限,如果需要设置权限,则使用命令 -v hostFile:containerFile:ro
- 如果没有指定hostFile,即命令如果为 -v containerFile 则宿主机的默认目录为 /var/lib/docker/volumes/ 下,具体的映射关系可以使用命令查看 docker inspect [容器名称]|grep /var/lib/docker/volumes
- 注意:目录只能挂载目录,文件只能挂载文件!
[root@localhost test]# pwd /usr/local/test [root@localhost test]# cat web.list 192.168.0.1 192.168.0.2 192.168.0.3 运行容器,ro表示该文件在容器内是只读的 [root@localhost test]# docker run -tid --name redis -v /usr/local/test/web.list:/usr/local/test/web.list:ro redis /bin/bash 038603af3e21e509a827f1f18ab749ffd9e3a31982ce1f58936a710aa0bcbe6e [root@localhost test]# docker exec -it redis /bin/bash root@038603af3e21:/data# cat /usr/local/test/web.list 192.168.0.1 192.168.0.2 192.168.0.3 容器内修改文件,发现会提示该文件是只读的 root@038603af3e21:/data# echo '192.168.0.4' >> /usr/local/test/web.list bash: /usr/local/test/web.list: Read-only file system
[root@localhost test]# mkdir -p /usr/local/dalomao [root@localhost test]# echo 'test' > /usr/local/dalomao/test [root@localhost test]# echo 'test1' > /usr/local/dalomao/test1 [root@localhost test]# docker run -tid --name redis -v /usr/local/dalomao:/usr/local/dalomao redis /bin/bash ee4ea05150476c6da22512597028ed18b17a1737f7644ebdad896e4ade389e97 容器上查看并修改 [root@localhost test]# docker exec -it redis /bin/bash root@ee4ea0515047:/data# cd /usr/local/dalomao/ root@ee4ea0515047:/usr/local/dalomao# ls test test1 root@ee4ea0515047:/usr/local/dalomao# cat test test root@ee4ea0515047:/usr/local/dalomao# cat test1 test1 root@ee4ea0515047:/usr/local/dalomao# echo '1234' >> test root@ee4ea0515047:/usr/local/dalomao# echo '4311' >> test1 宿主机上查看 root@ee4ea0515047:/usr/local/dalomao# exit exit [root@localhost test]# cat /usr/local/dalomao/test test 1234 [root@localhost test]# cat /usr/local/dalomao/test1 test1 4311
[root@localhost test]# mkdir -p /usr/local/dalomao/data1 [root@localhost test]# mkdir -p /usr/local/dalomao/data2 [root@localhost test]# echo '123456' > /usr/local/dalomao/data1/test1 [root@localhost test]# echo 'abcdef' > /usr/local/dalomao/data2/test2 [root@localhost test]# docker run -tid --name redis -v /usr/local/dalomao/data1:/usr/local/dalomao/data1 -v /usr/local/dalomao/data2:/usr/local/dalomao/data2 redis /bin/bash ef4d028958386f09352275daf9964f1fad259264e10a5662de46114cef50a0ca 容器内查看并修改 [root@localhost test]# docker exec -ti redis /bin/bash root@ef4d02895838:/data# ls /usr/local/dalomao/data1 test1 root@ef4d02895838:/data# ls /usr/local/dalomao/data2 test2 root@ef4d02895838:/data# cat /usr/local/dalomao/data1 cat: /usr/local/dalomao/data1: Is a directory root@ef4d02895838:/data# cat /usr/local/dalomao/data1/test1 123456 root@ef4d02895838:/data# cat /usr/local/dalomao/data2/test2 abcdef root@ef4d02895838:/data# echo 'data1' >> /usr/local/dalomao/data1/test1 root@ef4d02895838:/data# echo 'data2' >> /usr/local/dalomao/data2/test2
启动一个名为container1容器,此容器包含两个数据卷/var/volume1和/var/volume2,这两个目录是在容器里的,运行容器时会自动创建
[root@localhost test]# docker run -tid --name container1 -v /var/volume1 -v/var/volume2 redis /bin/bash
61a8b7761e96c01798a0e77371bf5e74546e469a747b38f457d68011dbdf6486
[root@localhost test]# docker inspect container1|grep /var/lib/docker/volumes
"Source": "/var/lib/docker/volumes/5bde8e911fe864a982a67800eca3313a92d116cfec7d5667cc09d5d44ff31196/_data",
"Source": "/var/lib/docker/volumes/4323c7faa7eb1e2a29e52f9c65983e0016054b0dc23dd15faa41c30c7f0ad846/_data",
"Source": "/var/lib/docker/volumes/fd74c2f2e44d7fba2e5c1257e99eec14009af96e0a1f1c09fb46f642c2b3ab83/_data",
创建container2容器,挂载container1容器中的数据卷
[root@localhost test]# docker run -tid --rm --volumes-from container1 --name container2 redis /bin/bash 4bb09861542a6bc2eb6a9e98049a5b54953a76c57f1ecc637468ca10b48dc0dd 登陆容器2查看并修改内容 [root@localhost test]# docker exec -ti container2 /bin/bash root@4bb09861542a:/data# ls /var/volume1 root@4bb09861542a:/data# ls /var/volume2 root@4bb09861542a:/data# echo 'this is volume1' > /var/volume1/test1 root@4bb09861542a:/data# echo 'this is volume2' > /var/volume2/test2 登陆容器1查看修改后的内容 root@4bb09861542a:/data# exit exit [root@localhost test]# docker exec -ti container1 /bin/bash root@61a8b7761e96:/data# cat /var/volume1/test1 this is volume1 root@61a8b7761e96:/data# cat /var/volume2/test2 this is volume2
再创建一个container3,挂载container2中从container1挂载的数据卷,当然也可以直接挂载初识的container1容器的数据卷
[root@localhost test]# docker run -tid --rm --volumes-from container2 --name container3 redis /bin/bash
63c57cd4bc183f7d41e18e86e3359e6a431eae3015b6c4056f0035e7e6ff3783
[root@localhost test]# docker exec -ti container3 /bin/bash
root@63c57cd4bc18:/data# cat /var/volume1/test1
this is volume1
root@63c57cd4bc18:/data# cat /var/volume2/test2
this is volume2
- 即使删除了初始的数据卷容器container1,或者是删除了其他容器,但只要是有容器在使用该数据卷,那么它里面的数据就不会丢失
- 命令中的rm表示当容器退出即停止的时候,会自动删除该容器
创建一个容器container1,包含两个数据卷/var/volume1和/var/volume2(这两个目录是在容器里的数据卷路径)
[root@localhost test]# docker run -tid -v /var/volume1 -v /var/volume2 --name container1 redis /bin/bash
2a76939f65eac00110dfff3bc3e0dd99a33804e2175397133184449afb2af731
[root@localhost test]# docker exec -ti redis /bin/bash
[root@localhost test]# docker exec -ti container1 /bin/bash
root@2a76939f65ea:/data# echo 'test1' > /var/volume1/test1
root@2a76939f65ea:/data# echo 'test11' > /var/volume1/test11
root@2a76939f65ea:/data# echo 'test2' > /var/volume2/test2
root@2a76939f65ea:/data# echo 'test22' > /var/volume2/test22
root@2a76939f65ea:/data# ls /var/volume1
test1 test11
root@2a76939f65ea:/data# ls /var/volume2
test2 test22
接下来进行数据卷的备份操作
使用–volumes-from来创建一个加载container1容器卷的容器,并从宿主机挂载当前所在目录到容器的/backup目录,容器内会tar压缩/var/colume1目录下的文件到/backup/backup1.tar,因为宿主机当前目录已经映射到/backup目录了,因此会在宿主机当前目录也存在该压缩包。备份完毕后–rm自动删除该创建的容器。
备份container1容器中的/var/volume1数据卷数据 -tid这个参数加不加都可以 --rm加上,备份后就会自动删除这个容器,如果不加这个--rm参数,那么备份后的容器就会保留,docker ps -a就会查看到) $(pwd)表示当前宿主机目录 [root@localhost test]# pwd /usr/local/test [root@localhost test]# docker run -tid --rm --volumes-from container1 -v $(pwd):/backup redis tar cvf /backup/backup1.tar /var/volume1 67b1eda88b832c29db7d5e0850fe31955b83ad0c244b657ac30e2e3f18e416a3 本地目录就会生成backup1.tar文件 解压后的目录结构是: --var --volume1 --test1 --test11 [root@localhost test]# ls backup1.tar
备份container1容器中的/var/volume2数据卷数据
[root@localhost test]# pwd
/usr/local/test
[root@localhost test]# docker run -tid --rm --volumes-from container1 -v $(pwd):/backup redis tar cvf /backup/backup2.tar /var/volume2
896adf78f9b6a06d6543b72e4977d6d16cb623157ee09f22a7fc6a8367e72478
[root@localhost test]# ll
total 24
-rw-r--r--. 1 root root 10240 Oct 15 01:20 backup1.tar
-rw-r--r--. 1 root root 10240 Oct 15 01:36 backup2.tar
备份container1容器中的/var/volume1和/var/volume2数据卷数据
[root@localhost test]# pwd
/usr/local/test
[root@localhost test]# docker run -tid --rm --volumes-from container1 -v $(pwd):/backup redis tar cvf /backup/backup.tar /var/volume1 /var/volume2
60c7b06e27708e98a1f8ddf48a8e287af152699e88026fa75b6133a4b2977be9
[root@localhost test]# ll
total 36
-rw-r--r--. 1 root root 10240 Oct 15 01:20 backup1.tar
-rw-r--r--. 1 root root 10240 Oct 15 01:36 backup2.tar
-rw-r--r--. 1 root root 10240 Oct 15 01:38 backup.tar
使用备份数据卷一章中的容器container1和备份数据卷backup.tar进行恢复操作
之前的数据卷是从container1中备份的,现在模拟container1数据卷丢失,然后直接用之前备份的backup.tar进行恢复
为了测试恢复,先删除容器里原先的数据(注意:数据卷目录不能删除,只能删除其中的数据) root@2a76939f65ea:/data# ls /var/volume2 test2 test22 root@2a76939f65ea:/data# rm -rf /var/volume1 /var/volume2 rm: cannot remove '/var/volume1': Device or resource busy rm: cannot remove '/var/volume2': Device or resource busy root@2a76939f65ea:/data# ls /var/volume1 root@2a76939f65ea:/data# ls /var/volume2 进行数据卷恢复,恢复数据卷中的所有数据 root@2a76939f65ea:/data# exit exit [root@localhost test]# pwd /usr/local/test [root@localhost test]# ll total 36 -rw-r--r--. 1 root root 10240 Oct 15 01:20 backup1.tar -rw-r--r--. 1 root root 10240 Oct 15 01:36 backup2.tar -rw-r--r--. 1 root root 10240 Oct 15 01:38 backup.tar 注意-C后面的路径,表示将数据恢复到容器里的路径直接使用压缩包中文件的各个路径。比如压缩包中的结果如下: --var --volume1 --test1 --test11 --volume2 --test22 --test22 则直接将文件解压到 /var/volume1和/var/volume2目录 [root@localhost test]# docker run --rm --volumes-from container1 -v $(pwd):/backup redis tar xvf /backup/backup.tar -C / var/volume1/ var/volume1/test1 var/volume1/test11 var/volume2/ var/volume2/test2 var/volume2/test22 登陆容器,查看数据卷已经正确恢复 [root@localhost test]# docker exec -ti container1 /bin/bash root@2a76939f65ea:/data# ls /var/volume1 test1 test11 root@2a76939f65ea:/data# ls /var/volume2 test2 test22
新建一个容器container2 [root@localhost test]# docker run -tid -v /var/volume1 -v /var/volume2 --name container2 redis /bin/bash 75b28049c3823843fb2e0fd8bae87671f0cf4ea27b495a4f725821c4edb2883a [root@localhost test]# docker exec -ti container2 /bin/bash root@75b28049c382:/data# ls /var/volume1 root@75b28049c382:/data# ls /var/volume2 开始恢复 root@75b28049c382:/data# exit exit [root@localhost test]# pwd /usr/local/test [root@localhost test]# ll total 36 -rw-r--r--. 1 root root 10240 Oct 15 01:20 backup1.tar -rw-r--r--. 1 root root 10240 Oct 15 01:36 backup2.tar -rw-r--r--. 1 root root 10240 Oct 15 01:38 backup.tar [root@localhost test]# docker run --rm --volumes-from container2 -v $(pwd):/backup redis tar xvf /backup/backup.tar -C / var/volume1/ var/volume1/test1 var/volume1/test11 var/volume2/ var/volume2/test2 var/volume2/test22 查看确实已经恢复了 [root@localhost test]# docker exec -ti container2 /bin/bash root@75b28049c382:/data# ls /var/volume1 test1 test11 root@75b28049c382:/data# ls /var/volume2 test2 test22
注意:
- 新容器创建时挂载的数据卷路径最好和之前备份的数据卷路径一致
- 新容器创建时,如果挂载的数据卷只是备份数据卷的一部分,那么恢复的时候也只是恢复一部分数据。比如新建容器挂载数据卷为-v /var/voluem1,那么使用backup.tar恢复时,只会恢复/var/volume1的数据,/var/volume2的数据是不会恢复的
- 如果新容器创建时挂载的数据卷目录和备份的数据卷目录不一致,那么数据恢复不了,除非修改 -C 后面的路径,比如新建容器时指定数据卷目录为 /var/volume,恢复时也是用 -C /var/volume,则是可以成功恢复的
Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。如果需要在删除容器的同时移除数据卷,可以在删除容器的时候使用 docker rm -v 这个命令。无主的数据卷可能会占据很多空间,要清理会很麻烦
- docker volume ls 列出所有的数据卷
- docker volume ls --filter dangling=true 过滤不在使用的数据卷
- docker volume rm [volume name] 删除一个数据卷,容器正在使用的数据卷不能删除,绑定挂载的数据卷无法删除
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。