一、前言
当我们使用Docker创建一个mysql的container, 数据是存储在container内的.
如果有一天不小心执行了docker rm $(docker ps -aq)删除所有container. 那么mysql里的数据也会被删掉, 这是不安全的.
我们需要将数据持久化, 存储在container外部. 即使删除container也不会删除原有的数据.
二、容器的缺陷
容器中的数据可以存储在容器层。但是将数据存放在容器层存在以下问题:
1.数据不是持久化。意思是如果容器删除了,这些数据也就没了
2.主机上的其它进程不方便访问这些数据
3.对这些数据的I/O会经过存储驱动,然后到达主机,引入了一层间接层,因此性能会有所下降
三、data volume有两种挂载方式:
1)bind mount(用户管理):将宿主机上的某个目录或文件(不可以是没有格式化的磁盘文件),挂载到容器中,默认在容器内对此目录是有读写权限的,如果只需要向容器内添加文件,不希望覆盖目录,需要注意源文件必须存在,否则会被当做一个目录bind mount给容器。
2)docker manager volume(docker自动管理):不需要指定源文件,只需要指定mount point(挂载点)。把容器里面的目录映射到了本地。
这种方式相比bind mount 缺点是无法限制对容器里边目录或文件的权限。
使用第二种挂载方式,-v 挂载时,不指定源文件位置,则默认挂载的路径是:
[[email protected] _data]# pwd
/var/lib/docker/volumes/dd173640edd5b0205bb02f3c4139647be12528b38289b9f93f18123a6b1266a8/_data
#当有目录挂载时,默认在/var/lib/docker/volumes/下会生成一串hash值,hash值下有一个_data的目录,容器内映射的文件就在此路径下。
四、Storage Driver
数据存储方式
Centos7版本的docker,Storage Driver(数据存储方式)为:overlay2 ,Backing Filesystem(文件系统类型): xfs
可使用 “docker inspect 容器名称” 来查看数据存储方式
五、Data Volume
(Bind mount)
持久化存储:本质上是DockerHost文件系统中的目录或文件,能够直接被Mount到容器的文件系统中。在运行容器时,可通过-v实现。
特点:
**1. Data Volume是目录或文件,不能是没有格式化的磁盘(块设备)。
- 容器可以读写volume中的数据。
- Volume数据可以永久保存,即使使用它的容器已经被销毁。**
小实验:
运行一个nginx服务,做数据持久化
(1)Data Volume是目录或文件,不能是没有格式化的磁盘(块设备)。
[[email protected] ~]# mkdir html
//创建测试目录
[[email protected] ~]# cd html/
[[email protected] html]# echo "This is a testfile in dockerHost." > index.html
//创建测试网页
[[email protected] ~]# docker run -itd --name testweb -v /root/html/:/usr/share/nginx/html nginx:latest
//运行一个nginx容器,并挂载目录
[[email protected] ~]# docker inspect testweb
[[email protected] ~]# curl 172.17.0.3
注意:dockerhost上需要被挂载的源文件或目录,必须是已经存在,否则,会被当作一个目录挂载到容器中。
(2)容器可以读写volume中的数据。
[[email protected] ~]# docker exec -it testweb /bin/bash
[email protected]:/# cd /usr/share/nginx/html/
[email protected]:/usr/share/nginx/html# echo "update" > index.html
//容器中更新网页
[email protected]:/usr/share/nginx/html# exit
[[email protected] ~]# cat html/index.html
//可以看到宿主目录的挂载目录也更新了
(3)Volume数据可以永久保存,即使,使用它的容器已经被销毁,也可以通过宿主机的挂在目录重新启动一个容器挂载这个目录进行访问。
[[email protected] ~]# docker ps -a -q |xargs docker rm -f
//删除所有容器
[[email protected] ~]# cat html/index.html
//容器删除之后,宿主机的测试网页也在
[[email protected] ~]# docker run -itd --name t1 -P -v /root/html/:/usr/share/nginx/html nginx:latest
//基于测试网页创建一个容器
[[email protected] ~]# docker ps
[[email protected] ~]# curl 127.0.0.1:32768
//访问一下
[[email protected] ~]# echo "update-new" > html/index.html
//再次更新测试网页
[[email protected] ~]# curl 127.0.0.1:32768
//在宿主机更新测试网页,刚刚创建的容器的测试网页也会更新
(5)默认挂载到容器内的文件,容器是有读写权限。可以在运行容器是-v 后边加“:ro”限制容器的写入权限
[[email protected] ~]# docker run -itd --name t2 -P -v /root/html/:/usr/share/nginx/html:ro nginx:latest
//创建容器设置指读权限
[[email protected] ~]# docker exec -it t2 /bin/bash
//进入容器
[email protected]:/# cd /usr/share/nginx/html
[email protected]:/usr/share/nginx/html# echo 1234 > index.html
//修改测试网页(失败,因为是只读的)
[[email protected] ~]# echo 654321 > html/index.html
//宿主机可以更改
[[email protected] ~]# curl 127.0.0.1:32768
(6)并且还可以挂载单独的文件到容器内部,一般他的使用场景是:如果不想对整个目录进行覆盖,而只希望添加某个文件,就可以使用挂载单个文件。
<1>测试1
[[email protected] ~]# docker run -itd --name v6 -P -v /root/html/index.html:/usr/share/nginx/html/index.html nginx:latest
[[email protected] ~]# docker ps
[[email protected] ~]# curl 127.0.0.1:32770
<1>测试2
[[email protected] ~]# echo test > test.html
[[email protected] ~]# docker run -itd --name t8 -P -v /root/test.html:/usr/share/nginx/html/test.html nginx:latest
[[email protected] ~]# curl 127.0.0.1:32772/test.html
六,Docker Manager Volume
会自动在宿主机生成目录,所以在挂载目录的时候只用写容器中的目录。
[[email protected] ~]# docker run -itd --name t1 -P -v /usr/share/nginx/html nginx:latest
[[email protected] ~]# docker ps
[[email protected] ~]# docker inspect t1
[[email protected] _data]# cd /var/lib/docker/volumes/17c50a065a6b10ccd01ca1ce8091fdf6282dc9dcb77a0f6695906257ecc03a63/_data
[[email protected] _data]# echo "this is a testfile" > index.html
[[email protected] _data]# docker ps
[[email protected] _data]# curl 127.0.0.1:32777
[[email protected] _data]# docker volume ls
[[email protected] _data]# docker rm t1 -f
[[email protected] _data]# cat index.html
1.删除容器的操作,默认不会对dockerhost上的源文件操作,如果想要在删除容器时把源文件也删除,可以在删除容器时添加-v选项(一般不推荐使用这种方式,因为文件有可能被其他容器使用)
[[email protected] _data]# docker run -itd --name t2 -P -v /usr/share/nginx/html nginx:latest
[[email protected] ~]# docker inspect t2
[[email protected] ~]# cd /var/lib/docker/volumes/2781dbfdc673fc7d149dc4f6217ef277fe72e05ba2e20fcebb617afe97eccb30/_data
[[email protected] _data]# docker rm -v t2 -f
t2
[[email protected] _data]# ls
七,容器与容器的数据共享
Volume container:给其他容器提供volume存储卷的容器。并且它可以提供bind mount,也可以提供docker manager volume。
创建一个vc_data容器
[[email protected] ~]# docker create --name vc_data -v ~/html:/usr/share/nginx/html -v /other/useful/tools busybox
[[email protected] ~]# docker inspect vc_data
[[email protected] ~]# docker run -itd --name t3 -P --volumes-from vc_data nginx:latest
[[email protected] ~]# docker ps
[[email protected] ~]# curl 127.0.0.1:32779
原文地址:https://blog.51cto.com/14320361/2459668