基础篇 容器数据卷
内容概述
容器数据卷技术说白了就是:数据持久化与同步。
# 1. 数据卷简介
通过前面的学习我们知道,docker 可以将引用和环境打包成一个镜像!但是我们在容器中产生的数据无法打包,那么数据都在容器中,那么我们容器删除,数据就会丢失! 因此,这里我们就有一个新的需求:数据可以持久化。
思考下,如果我们正在使用MySQL ,如果因为某种意外或者需求把容器删了,我们的数据肯定就会消失,此时针对MySQL 这种应用我们的需求是: 数据可以存储在本地(宿主机)。
因此,容器之间可以有一个数据共享技术!可以让docker 容器中产生的数据同步到本地,这就是卷技术。目录的挂载,将容器内的目录挂载到Linux 宿主机上面。

总结一句话容器数据卷就是:容器的数据持久化和同步操作!容器间也可以数据共享。
# 1.1 数据卷特点
数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
数据卷可以在容器之间共享和重用- 对
数据卷的修改会立马生效 - 对
数据卷的更新,不会影响镜像 数据卷默认会一直存在,即使容器被删除
注意:
数据卷的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制)。
# 1.2 数据卷命令
# 1.2.1 创建数据卷
$ docker volume create 数据卷名
# 1.2.2 查看数据卷
$ docker volume inspect 数据卷名
# 1.2.3 挂载数据卷
$ docker run -v 数据卷名
# 1.2.4 删除数据卷
$ docker volume rm 数据卷名
# 2. 数据卷使用方式一:-v 命令挂载
# 2.1 指定路径挂载
-v 主机目录:容器内目录
示例:
[root@ibytehorizon home]# docker run -it -v /home/ceshi:/home centos /bin/bash
[root@f223bd9fb918 /]# cd home/
[root@ibytehorizon home]# ll
drwxr-xr-x 2 root root 6 Feb 23 11:13 ceshi
# 查看挂载信息
docker inspect 容器id
[
//.....
"Mounts": [ # 挂载 -v 卷
{
"Type": "bind",
"Source": "/home/ceshi", # 主机内地址
"Destination": "/home", # docker容器内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
//.....
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
文件同步(容器->宿主机)

文件同步(宿主机->容器)
1.停止容器
2.在宿主机上修改文件
3.启动容器
4.容器内部的数据依旧是同步的
2
3
4
综上,我们不难发现,-v 同步双向的,这样的好处就是:我们以后修改只需要在本地修改即可,容器内会自动同步。
# 2.2 匿名挂载
- 所谓匿名挂载,即:
-v 容器内路径,就是在-v 后面只写了容器内部路径,没有写容器外的路径。
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx # -P 大写表示随机映射端口
# 查看所有的volume 的情况
[root@ibytehorizon ~]# docker volume list
local 0f3cc2c9ce92141c4aae9dc3811bcb1f497bd74c3925314289ddde019bdb5256
2
3
4
5
6
# 2.3 具名挂载
- 所谓具名挂载,即:
-v 卷名:容器内路径,就是在-v 后面加卷名,再写容器内部路径,依然没有写容器外的路径。
# -v 卷名:容器内路径
[root@ibytehorizon ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
b38fdef08f286d0389b395458c4770291ea8f84a0ba0575c56f024ca1695f03a
[root@ibytehorizon ~]# docker volume ls
DRIVER VOLUME NAME
local 0f3cc2c9ce92141c4aae9dc3811bcb1f497bd74c3925314289ddde019bdb5256
local b7a5acf0719d4b02b4bedc7f582b35530ddc48995c252a62bdb9b267df9d6a1f
local juming-nginx
# 查看一下这个卷
[root@ibytehorizon ~]# docker volume inspect juming-nginx
[
{
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx", # 卷名
"Options": {},
"Scope": "local"
}
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
值得注意的是,所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxx/_data
通过具名挂载可以方便的找到我们使用的一个卷,大多数情况在使用具名挂载。
综上,挂载一共以下三个方式:
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
2
3
# 2.4 实战案例:安装MySQL
思考:mysql 的数据持久化
# step1:获取镜像
[root@ibytehorizon ~]# docker pull mysql:5.7
# step2:运行容器
# 1. 启动容器需要做数据挂载
# 2. 安装启动mysql,需要配置密码
# 官方配置密码启动 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动
# -d 后台运行
# -p 端口映射
# -v 数据卷挂载
# --name 容器别名
# -e 环境配置
# MYSQL_ROOT_PASSWORD mysql密码
[root@ibytehorizon home]# 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=1qaz2wsx --name mysql01 mysql:5.7
# step3:启动成功之后,我们使用本地工具Navicat 连接测试,需要注意如果是宿主机防火墙需要放开相关端口
# step4:在本地测试创建一个数据库,查看我们映射的路径时候ok
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
假设我们将容器删除,发现我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能!

# 2.5 读写权限
-v 卷名:ro|rw
- ro:readonly 只读权限,如果是ro 就说明这个路径只能通过宿主机来操作,容器内是无法操作的!
- rw:readwrite 读写权限,默认权限。
注意:一旦设置了容器权限,容器对我们挂载出来的内容就有限定了。
[root@ibytehorizon ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
[root@ibytehorizon ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
2
# 3. 数据卷使用方式二:Dockerfile 构建镜像挂载
# 3.1 Dockerfile 简介
Dockerfile 就是用来构建docker镜像命令脚本文件!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个一个命令,每个命令都是一层。
# 3.2 Dockerfile 挂载
- 创建一个Dockerfile 文件,文件名可以随意,建议就是Dockerfile。
- 文件中的内容采用类似键值对的形式,指令(大写) 参数。
- 这里的每一个命令,就是镜像的一层。
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
2
3
4
5
6
# docker build -f dockerfile文件名 -t 镜像名 .
# 注意:最后那个. 一定不能缺少
[root@ibytehorizon docker-test-volume]# docker build -f dockerfile -t mycentos .
Sending build context to Docker daemon 2.048 kB
Step 1/4 : FROM centos
---> 300e315adb2f
Step 2/4 : VOLUME volume01 volume02
---> Running in 132ca2398c11
---> 28796ac5c095
Removing intermediate container 132ca2398c11
Step 3/4 : CMD echo "----end----"
---> Running in bb94f92cdd7d
---> 95490287d9a0
Removing intermediate container bb94f92cdd7d
Step 4/4 : CMD /bin/bash
---> Running in a821ae81629a
---> bf8c238b2fb7
Removing intermediate container a821ae81629a
Successfully built bf8c238b2fb7
[root@ibytehorizon docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos latest bf8c238b2fb7 54 seconds ago 209 MB
tomcat02 1.0 0d802e29f5d0 5 hours ago 653 MB
mysql 5.7 a70d36bc331a 5 weeks ago 449 MB
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
启动自己生成的容器
docker run -it mycentos /bin/bash

这个卷和外部一定有一个同步目录,通过inspect 命令查看
docker inspect 83cacb779d3c

查看一下卷挂载路径
cd /var/lib/docker/volumes/

这种方式我们未来使用非常多,因为我们通常会构建自己的镜像!
假设构建镜像时候没有挂载卷,要手动具名挂载 -v 卷名:容器内路径。
# 4. 数据卷使用方式三:--volumes-from
# 4.1 多个mysql同步数据

--volumes-from
# --volumes-from 相当于继承 docker01数据卷容器
[root@ibytehorizon ~]# docker run -it --name docker01
[root@ibytehorizon ~]# docker run -it --name docker02 --volumes-from docker01 bf8c238b2fb7
[root@e713c6e04043 /]# ls -al
total 0
drwxr-xr-x 1 root root 78 Feb 23 08:30 .
drwxr-xr-x 1 root root 78 Feb 23 08:30 ..
-rwxr-xr-x 1 root root 0 Feb 23 08:30 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x 5 root root 360 Feb 23 08:30 dev
drwxr-xr-x 1 root root 66 Feb 23 08:30 etc
drwxr-xr-x 2 root root 6 Nov 3 15:22 home
lrwxrwxrwx 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------ 2 root root 6 Dec 4 17:37 lost+found
drwxr-xr-x 2 root root 6 Nov 3 15:22 media
drwxr-xr-x 2 root root 6 Nov 3 15:22 mnt
drwxr-xr-x 2 root root 6 Nov 3 15:22 opt
dr-xr-xr-x 144 root root 0 Feb 23 08:30 proc
dr-xr-x--- 2 root root 162 Dec 4 17:37 root
drwxr-xr-x 11 root root 163 Dec 4 17:37 run
lrwxrwxrwx 1 root root 8 Nov 3 15:22 sbin -> usr/sbin
drwxr-xr-x 2 root root 6 Nov 3 15:22 srv
dr-xr-xr-x 13 root root 0 Feb 23 08:30 sys
drwxrwxrwt 7 root root 145 Dec 4 17:37 tmp
drwxr-xr-x 12 root root 144 Dec 4 17:37 usr
drwxr-xr-x 20 root root 262 Dec 4 17:37 var
drwxr-xr-x 2 root root 6 Feb 23 08:27 volume01
drwxr-xr-x 2 root root 6 Feb 23 08:27 volume02
[root@e713c6e04043 /]# cd volume01/
[root@e713c6e04043 volume01]# ls # docker01创建的内容同步到了docker02上面
docker01
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@ibytehorizon ~]# docker run -it --name docker03 --volumes-from docker01 bf8c238b2fb7
[root@733a75f98da7 /]# cd volume01/
[root@733a75f98da7 volume01]# ls
docker01
[root@733a75f98da7 volume01]# touch docker 03
[root@733a75f98da7 volume01]# ls
03 docker docker01
[root@733a75f98da7 volume01]#
# 查看docker01的文件
[root@285046dc311c volume01]# ls
03 docker docker01
[root@285046dc311c volume01]#
2
3
4
5
6
7
8
9
10
11
12
13
结论:通过--volumes-from 可以实现容器间的数据共享。
PS:删除docker01 查看docker02和docker03时候还可以访问这个文件。
# 4.2 多个mysql实现数据共享
通过--volumes-from可以实现两个容器数据同步!
[root@ibytehorizon home]# docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=1qaz2wsx --name mysql01 mysql:5.7
[root@ibytehorizon home]# docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=1qaz2wsx --name mysql02 --volumes-from mysql01 mysql:5.7
2
结论:
容器之间配置信息的传递,数据卷容器的生命周期会一直持续到没有容器使用为止。
但是一旦持久化到了本地,这时候,本地的数据是不会删除的。