1. 什么是容器数据卷?
docker的理念回顾
将应用和环境打包成一个镜像。
数据?如果数据都在容器中,那么我们将容器删除,数据就会丢失!需求:数据可以持久化。
MySQL,容器删除了,就相当于删库跑路!需求:MySQL数据可以存储在本地!
迫切希望有一个技术:容器之间可以有一个数据共享的技术!docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!
总结:卷的技术就是为了容器的持久化和同步操纵!容器间也是可以数据共享的!
2. 使用数据卷
方式一:直接使用命令来挂载 -v
指定路径挂载
docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口 镜像名称#测试docker run -it -v /home/ceshi/:/home centos /bin/bash#启动起来之后通过docker inspect 容器id 查看挂载的状况"Mounts": [{"Type": "bind","Source": "/home/ceshi","Destination": "/home","Mode": "","RW": true,"Propagation": "rprivate"}],在主机上touch一个新文件,在容器内也可以查看到,即使容器是关闭状态,文件依然会同步到容器内


好处:我们以后修改只需要在本地修改即可,容器内会自动同步
实战:安装 MySQL
思考MySQL的数据持久化问题
#获取镜像root@kylin:/home# docker pull mysql:5.7#运行容器时做数据挂载-d 后台运行-p 端口映射-v 卷挂载-e 环境配置--name 指定名称docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d --name mysql01 mysql:5.7#启动成功后,在本地使用Mysql-Front连接远程数据库sql-front-连接到服务器的3310 --- 3310 和容器的3306 映射,这个时候就可以连接上了#在本地测试,创建一个数据库,查看一下我们映射的数据库
假设我们将容器删除,经过实践检验,我们挂载到本地的数据卷依旧没有丢失。这就实现了容器数据持久化教程。
具名挂载和匿名挂载
查看所有的卷(volume)的情况:
root@kylin:/home# docker volume ls DRIVER VOLUME NAME local 2d0943a371b16346b21c87357353e4a322f284e2544d1b03721c050601852692 local 09daf4be8ff4158082feded9f103173ea9cb3718aa41369769d3fa78de76b84b local 825c11e64035e76509a5ea0db6879477d022419054befd8560a159ce3478154f local 40719dd645f1369bdd96315ac23ba09414188a869ac19b3d40d3c18f20ccaf22
这里发现,这种就是匿名挂载,我们只写了容器内的路径,没有写容器外的路径
通过docker volume inspect volume_name 查看匿名卷的信息
root@kylin:/home# docker volume inspect 40719dd645f1369bdd96315ac23ba09414188a869ac19b3d40d3c18f20ccaf22 [ { “CreatedAt”: “2020-08-08T11:39:28+08:00”, “Driver”: “local”, “Labels”: null, “Mountpoint”: “/var/lib/docker/volumes/40719dd645f1369bdd96315ac23ba09414188a869ac19b3d40d3c18f20ccaf22/_data”, “Name”: “40719dd645f1369bdd96315ac23ba09414188a869ac19b3d40d3c18f20ccaf22”, “Options”: null, “Scope”: “local” } ]
- 具名挂载```shell#具名挂载方式开启容器-v 卷名:容器内路径root@kylin:/home# docker run -d -P --name nginx4 -v juming_nginx:/etc/nginx nginx#查看所有的卷root@kylin:/home# docker volume lsDRIVER VOLUME NAMElocal 2d0943a371b16346b21c87357353e4a322f284e2544d1b03721c050601852692local 09daf4be8ff4158082feded9f103173ea9cb3718aa41369769d3fa78de76b84blocal 825c11e64035e76509a5ea0db6879477d022419054befd8560a159ce3478154flocal 40719dd645f1369bdd96315ac23ba09414188a869ac19b3d40d3c18f20ccaf22local juming_nginx#查看具名挂载的卷的信息root@kylin:/home# docker volume inspect juming_nginx[{"CreatedAt": "2020-08-08T11:47:01+08:00","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/juming_nginx/_data","Name": "juming_nginx","Options": null,"Scope": "local"}]
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的 具名挂载
判断 具名/匿名/指定路径 挂载
#如何确定是 具名挂载 还是 匿名挂载 , 还是指定路径挂载-v 容器内路径 # 匿名挂载-v 卷名:容器内路径 # 具名挂载-v /宿主机路径:容器内路径 # 指定路径挂载
扩展:
# 通过 -v 容器内路径[:ro|:rw] 改变读写权限ro readonly 只读rw readwrite 可读可写#一旦设置了容器权限,容器对我们挂载出来的内容就有限定了!docker run -d -P --name nginx4 -v juming_nginx:/etc/nginx:ro nginxdocker run -d -P --name nginx4 -v juming_nginx:/etc/nginx:rw nginx#ro 只要看到这个ro,就说明这个路径只能通过宿主机改变,容器内部是无法操作的
方式二:初识Dockerfile
Dockerfile 就是用来构建 docker镜像 的构建文件!命令脚本!
先写一个dockerfile脚本,通过这个脚本可以生成一个镜像,镜像是一层层的,所以每个脚本就是一个一个的命令,每个命令都是一层!
#创建一个dockerfile文件,名字可以随机,建议dockerfile#文件内容 (下面的每个命令都是镜像的一层)FROM centosVOLUME ["volume01","volume02"] //匿名方式挂载两个卷CMD echo "------end"CMD /bin/bash#执行构建命令注意最后面有个点,并且镜像名的最前面不能有"/"docker build -f dockerfile1 -t kylin/centos .#结果显示root@kylin:/home/docker_volume_test# docker build -f dockerfile1 -t kylin/centos .Sending build context to Docker daemon 2.048kBStep 1/4 : FROM centos---> 831691599b88Step 2/4 : VOLUME ["volume01","volume02"]---> Running in ee6ff7b33bbfRemoving intermediate container ee6ff7b33bbf---> 778da48c9617Step 3/4 : CMD echo "------end"---> Running in 5346f74b5915Removing intermediate container 5346f74b5915---> 5812457cde63Step 4/4 : CMD /bin/bash---> Running in c42e0db993d9Removing intermediate container c42e0db993d9---> fb7d10d0b5d6Successfully built fb7d10d0b5d6Successfully tagged kylin/centos:latest

- 启动自己写的容器

注意看,最下面有两个卷,那就是我们自己挂载的。
这个卷和外部一定有一个同步的目录,通过 docker inspect 容器id 查看挂载的卷在本地什么位置
我们在容器中的volume01中写一个文件container.txt,然后在宿主机的相应位置查看一下:
"Mounts": [{"Type": "volume","Name": "9e316914bbd76835e86062950702ce71c8cac3f631fbe0bcbe1a31e2fe047193","Source": "/var/lib/docker/volumes/9e316914bbd76835e86062950702ce71c8cac3f631fbe0bcbe1a31e2fe047193/_data","Destination": "volume02","Driver": "local","Mode": "","RW": true,"Propagation": ""},{"Type": "volume","Name": "a7bad1d08e0f226fbaededce48798cf6f114076dfcf955639687c0a3bfeb7c75","Source": "/var/lib/docker/volumes/a7bad1d08e0f226fbaededce48798cf6f114076dfcf955639687c0a3bfeb7c75/_data","Destination": "volume01","Driver": "local","Mode": "","RW": true,"Propagation": ""}],
在宿主机进入volume01相对应的目录,然后查看
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像的时候没有挂载卷,要手动镜像挂载: -v 卷名:容器内路径 !
3. 数据卷容器
开启容器1: docker01
#开启容器01docker run -it --name docker01 kylin/centos
开启容器2: docker02
(注意:使用 —volumes-from docker01 继承 docker01 的 volumes )
docker run -it --name docker02 --volumes-from docker01 kylin/centos
成功开启之后,在docker01的volume01目录创建一个名为docker01的文件,然后在docker02容器上能够看见。
开启容器3: docker03
(注意:使用 —volumes-from docker01 继承 docker01 的 volumes )
在容器3的volumes01目录下,创建一个名为docker03的文件,可以在docker01上看到同步的。
只要通过 --volumes-from (父)容器id ,就可以直接继承docker01的数据卷,实现数据同步。
虽然说是从docker01继承的,但其实是三个容器的数据卷相互同步。即使删除了docker01,docker02和docker03的数据也依然是存在的。
通过 docker inspect 查看每个容器的挂载信息,可以看见,他们三个容器都使用了同一个卷!!同一个卷!!
"Mounts": [{"Type": "volume","Name": "a89459225362be0282cce4137f9a1ef0a73bc4e7a046e985b2ba1ff033e30a35","Source": "/var/lib/docker/volumes/a89459225362be0282cce4137f9a1ef0a73bc4e7a046e985b2ba1ff033e30a35/_data","Destination": "volume02","Driver": "local","Mode": "","RW": true,"Propagation": ""},{"Type": "volume","Name": "676a0154ce4061f2922f9aec948672dfdf878ab1e514760e60cc15c35006da7c","Source": "/var/lib/docker/volumes/676a0154ce4061f2922f9aec948672dfdf878ab1e514760e60cc15c35006da7c/_data","Destination": "volume01","Driver": "local","Mode": "","RW": true,"Propagation": ""}],
作业:多个MySQL 实现数据共享
注意:
- mysql01 绑定了3310端口,那么mysql02就应该换一个其他的端口(3311)
- mysql02 直接通过
--volumes-from mysql01使用 mysql01 的数据卷即可 ```shell docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d —name mysql01 mysql:5.7
docker run -d -p 3311:3306 —volumes-from mysql01 -e MYSQL_ROOT_PASSWORD=123456 -d —name mysql02 mysql:5.7 ```
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的
