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