Docker容器数据卷详解
1. 什么是容器数据卷
docker的理念将运行的环境打包形成容器运行,运行可以伴随容器,但是我们对数据的要求是希望持久化,容器之间可以共享数据,Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为容器的一部分保存下来,那么当容器被删除之后,数据也就没了,为了能够保存数据,在docker容器中使用卷。
“卷” 就是目录或者文件,存在于一个或者多个容器中,但是不属于联合文件系统,因此能够绕过Union File System提供一些用于持久化数据或共享数据的特点,即Docker容器产生的数据,同步到本地
数据卷的作用:
卷的设计目的就是数据的持久化,完全独立与容器的生命周期,因此Docker不会在容器删除时删除其挂载的数据卷。
特点:
1. 数据卷可以在容器之间共享和重用数据。
2. 卷的更改可以直接生效。
3. 数据卷的更改不会包含在镜像的更新中。
4. 数据卷的生命周期一直持续到没有容器使用它为止。
容器的持久化
容器间继承+共享数据
Docker容器产生的数据同步到本地,这样关闭容器的时候,数据是在本地的,不会影响数据的安全性。
docker的容器卷技术也就是将容器内部目录和本地目录进行一个同步,即挂载(挂载不是等同于同步)。
挂载:
Docker容器产生的数据同步到本地,这样我们关闭容器的时候,数据被同步到了本地,不会影响数据的安全性,docker的容器卷技术就将容器内的目录挂载到外部的本地指定的目录上,这样容器内部所写的数据将会被同步到外部指定的本地目录上
2. 使用数据卷
运行容器,命令挂载数据卷:
docker run -it -v 主机目录:容器类目录
[root@node01 ~]# docker run -it -v /home/ceshi:/home centos /bin/bash
查看挂载是否成功 命令: docker inspect 容器id:
挂载成功以后,在docker容器内部的/home目录下创建的文件等数据都可以被同步到外部Linux下的/home/ceshi目录中,就算docker容器停止了,在外部修改的数据同样还是会被同步的docker容器内部
问题:
可以通过挂载的方式,将容器里面的目录挂载到虚拟机外部的某一个目录,这样就不需要每次修改就进入容器内部了,在本地修改照样可以同步到容器内部。
3. MySQL容器建立数据卷同步数据
1. Mysql数据库持久化的问题!
在Linux下的MySQL默认的数据文档存储目录为/var/lib/mysql,默认的配置文件的位置/etc/mysql/conf.d,为了确保MySQL镜像或容器删除后,造成的数据丢失,下面建立数据卷保存MySQL的数据和文件。
挂载及运行:(没下载回直接下载)
[root@node01 ~]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# -d 后台运行
# -p 端口映射
# -v 卷挂载
# -e 环境配置
# --name 容器名字
#-e MYSQL_ROOT_PASSWORD=123456 设置密码
运行以后测试连接外部sqlyog,并创建一个test数据库,再判断内部mysql是否也同步了这个test数据库:
去内部mysql 的data目录下查看是否同步,看如下图,发现确实同步。
那么我们进一步猜测,假设容器停止运行或者容器删除,本地的数据依旧不会丢失?
我这里测试结果是,假设容器停止运行或者容器删除,本地的数据依旧不会丢失,仍然可以实现数据同步。
2. 具名挂载和匿名挂载
匿名挂载
-v 容器内路径
[root@node01 home]# docker run -d -P --name nginx02 -v /etc/nginx nginx
具名挂载,我们通过具名挂载可以方便的找到我们的一个卷,大多数情况下使用具名,不建议使用匿名挂载
-v 卷的名字:容器内路径
[root@node01 home]# docker run -d -P --name nginx03 -v juming-nginx:/etc/nginx nginx
[root@node01 home]# docker volume ls
DRIVER VOLUME NAME
local 30472b4ad70c8a4a34b1395dc5e38ed31dd90c1958dd2e8d73ac2ca5b9016416
local juming-nginx
查看所有卷的使用情况 docker volume ls
[root@node01 home]# docker volume ls
DRIVER VOLUME NAME
local 30472b4ad70c8a4a34b1395dc5e38ed31dd90c1958dd2e8d73ac2ca5b9016416
local 59469d10de8363d8d46f585ff72672fde1637fff3acfc12c9fa3995e9334e5d0
local edb83b09fabcef2ed7231d88aa0c31034f05b383623bb9e0793122d9bdfe1b96
根据具名挂载指定的名字,查看卷的路径 docker volume inspect juming-nginx
匿名挂载,具名挂载 指定路径挂载的区别
-v 容器内路径 #匿名挂载
.
-v 卷名:容器内路径 #具名挂载
.
-v /宿主机路径:容器内路径 #指定路径挂载
拓展
指定数据卷映射的相关参数:
.
ro —— readonly 只读。设置了这个路径只能通过宿主机来操作,容器内部不能操作!!!
.
rw ----- readwrite 可读可写
4. 初始DockerFile,设置数据卷
Dockerfile 就是用来构建docker镜像的构建文件!命令脚本!
通过这个脚本生成一个镜像,镜像是一层层的,脚本一个个的命令,每个命令都是一层
匿名挂载了volume01和volume02两个数据卷
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
(这里是匿名挂载)
执行构建镜像的shell脚本
[root@node01 docker-test-volume]# docker build -f dockerfile1 -t climber/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in dd37d375547f
Removing intermediate container dd37d375547f
---> 152fea150946
Step 3/4 : CMD echo "----end----"
---> Running in fa115514e121
Removing intermediate container fa115514e121
---> 7ec6b3ac0917
Step 4/4 : CMD /bin/bash
---> Running in 61f13094701b
Removing intermediate container 61f13094701b
---> 43650b75dece
Successfully built 43650b75dece
Successfully tagged climber/centos:1.0
[root@node01 docker-test-volume]# docker images #查看刚构建的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
climber/centos 1.0 43650b75dece About a minute ago 231MB
启动自己生成的容器
[root@node01 docker-test-volume]# docker run -it 43650b75dece /bin/bash
查看数据卷目录挂载的位置
[root@node01 ~]# docker inspect e8318420cb26 #这里是容器id
......
"Mounts": [
{
"Type": "volume",
"Name": "fceffb6ede38b135f11cdd13fbb53cb5fde4269b575e8a7c533473c31d108360",
"Source": "/var/lib/docker/volumes/fceffb6ede38b135f11cdd13fbb53cb5fde4269b575e8a7c533473c31d108360/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "62d3668266dd89c1851ccb0e184360abff30caf15bfda43a7e11ef1da6766101",
"Source": "/var/lib/docker/volumes/62d3668266dd89c1851ccb0e184360abff30caf15bfda43a7e11ef1da6766101/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
......
可以看到Mounts下有宿主机的挂载目录。因为dockerfile中没有指定宿主机目录,所以属于匿名挂载,在/var/lib/docker/volumes/目录下生成了随机命名的路径。
这种挂载的方式以后经常使用,因为我们通常会构建自己的镜像
如果没有挂载卷的话,需要手动镜像挂载 “ -v 卷名:容器内路径 “
5. 数据卷容器
容器数据卷是指建立数据卷,来同步多个容器间的数据,实现容器间的数据同步。
先启动docker01
[root@node01 docker-test-volume]# docker run -it --name docker01 climber/centos:1.0
[root@002261dab7b8 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
再启动docker02,通过参数–volumes-from,设置容器2和容器1建立数据卷挂载关系,类似于java里面docker02这个了类 extends docker01这个类,docker01 就相当于一个数据卷容器,父容器数据卷里面的数据会同步到子容器数据卷。
[root@node01 ~]# docker run -it --name docker02 --volumes-from docker01 climber/centos:1.0
数据共享其实也可以说是以备份拷贝机制来实现共享。
6. 结论:
容器之间的配置信息的传递,数据卷容器的生命周期一直持续到没有容器为止
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的。