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 ls
DRIVER VOLUME NAME
local 2d0943a371b16346b21c87357353e4a322f284e2544d1b03721c050601852692
local 09daf4be8ff4158082feded9f103173ea9cb3718aa41369769d3fa78de76b84b
local 825c11e64035e76509a5ea0db6879477d022419054befd8560a159ce3478154f
local 40719dd645f1369bdd96315ac23ba09414188a869ac19b3d40d3c18f20ccaf22
local 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 nginx
docker run -d -P --name nginx4 -v juming_nginx:/etc/nginx:rw nginx
#ro 只要看到这个ro,就说明这个路径只能通过宿主机改变,容器内部是无法操作的
方式二:初识Dockerfile
Dockerfile 就是用来构建 docker镜像 的构建文件!命令脚本!
先写一个dockerfile脚本,通过这个脚本可以生成一个镜像,镜像是一层层的,所以每个脚本就是一个一个的命令,每个命令都是一层!
#创建一个dockerfile文件,名字可以随机,建议dockerfile
#文件内容 (下面的每个命令都是镜像的一层)
FROM centos
VOLUME ["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.048kB
Step 1/4 : FROM centos
---> 831691599b88
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in ee6ff7b33bbf
Removing intermediate container ee6ff7b33bbf
---> 778da48c9617
Step 3/4 : CMD echo "------end"
---> Running in 5346f74b5915
Removing intermediate container 5346f74b5915
---> 5812457cde63
Step 4/4 : CMD /bin/bash
---> Running in c42e0db993d9
Removing intermediate container c42e0db993d9
---> fb7d10d0b5d6
Successfully built fb7d10d0b5d6
Successfully 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
#开启容器01
docker 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 ```
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器为止。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的