Docker重学系列之高级数据卷配置
- 数据卷说明
- 为什么需要容器数据卷
- 数据卷使用
- 创建数据卷
- 查看数据卷
- 挂载数据卷
- 删除数据卷
- 具名挂载和匿名挂载
- 指定路径挂载
- 具名挂载
- 匿名挂载
- 容器与容器之间的数据共享 --volumes-from
数据卷说明
容器数据卷就是目录的挂载,将我们的容器的目录挂载到宿主机上,从而实现打通宿主机和容器之间的文件共享功能;
数据卷
是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
数据卷
可以在容器之间共享和重用- 对
数据卷
的修改会立马生效 - 对
数据卷
的更新,不会影响镜像 数据卷
默认会一直存在,即使容器被删除
注意:
数据卷
的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制)。
为什么需要容器数据卷
docker理念就是将应用和环境打包成一个镜像;但是数据怎么办呢?且不说数据库,一个项目在运行过程种肯定会产生大量的日志,这些日志对开发人员来说是非常重要的, 因为有了这些日志,我们才知道运行的过程中出现了哪些问题,然后进行排查找错;
但是在容器中,项目每次更新迭代都会将容器删除,直接替换新镜像运行;那么在这种情况下,要保存这些日志文件的话,如果每次都去往容器里复制到宿主机,这个工作量会有点大,并且如果日志文件太大的话,复制的工作也是很耗时耗力的;所以这时候就需要用到容器数据卷的功能了,说白了这个功能非常地简单,就是打通宿主和容器的文件共享功能;docker容器中产生的数据文件,会实时同步到宿主机中;相反的,宿主机产生的文件叶会同步到容器中;这样就打通了双向传输的管道;
容器和容器之间实现数据共享之后,就没有主容器和子容器之分了,因为它们共享的数据只有一份,是保存在宿主机上面的,删除任何一个容器,都不会影响其他容器的数据同步;
数据卷使用
代码语言:javascript复制数据卷使用 -v 宿主机路径:容器类路径
docker run -d -v 主机目录:容器目录 tomcat
运行以上命令后,会在容器和宿主机上自动创建相应的目录,在目录下创建或者修改文件都会自动同步过去;
注意: 必须在容器首次启动时指定
1.使用绝对路径的数据卷,用户自己管理
docker run -v /root/datas:/usr/local/tomcat/webapps .... tomcat:8.0
2.使用别名方式的数据卷,docker管理
docker run -v bb:/usr/local/tomcat/webapps .... tomcat:8.0
注意:
bb代表一个数据卷别名
bb这个数据别名可以存在,也可以不存在,不存在docker首次使用到的时候自动创建
第一次使用别名时将容器中原始数据留下来,使用绝对路径方式不会保留容器中原始数据
别名是什么: 别名代表一个docker自身维护的数据卷
1.查看所有docker维护的数据卷 docker volume ls
2.查看数据卷详细内容
docker inspect 容器名称/网桥名称/数据卷别名 --->docker inspect 名称: 有三重含义,默认先找容器名称相同的,再者是网桥,最后是数据卷
docker network inspect 查看网桥详细信息
docker volume inspect 查看数据卷详细信息
删除一个数据卷:
docker volume rm 数据卷别名
创建一个别名数据卷
docker volume create 数据卷别名
创建数据卷
代码语言:javascript复制[root@centos ~]# docker volume create my-vol
my-vol
查看数据卷
代码语言:javascript复制[root@centos ~]# docker volume inspect my-vol
[
{
"CreatedAt": "2020-11-25T11:43:56 08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
或
代码语言:javascript复制docker inspect 容器id/容器名称
执行以上命令后会打印一大堆已经格式化的json字符串,这时候我们找到key为 Mounts
的项就是容器数据卷的相关配置了,
"Mounts": [
{
"Type": "bind",
"Source": "/root/dockerContainer", # 宿主机的目录
"Destination": "/text", # 容器的目录
"Mode": "",
"RW": true, # RW可读可写;ro为只读,只能修改宿主机的文件;
"Propagation": "rprivate"
}
],
挂载数据卷
代码语言:javascript复制[root@centos ~]# docker run -d -P --name web -v my-vol:/usr/share/nginx/html nginx
[root@centos ~]# docker inspect web
"Mounts": [
{
"Type": "volume",
"Name": "my-vol",
"Source": "/var/lib/docker/volumes/my-vol/_data",
"Destination": "/usr/share/nginx/html",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
删除数据卷
代码语言:javascript复制docker volume rm my-vol
数据卷
是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷
,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷
。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。
无主的数据卷可能会占据很多空间,要清理请使用以下命令
代码语言:javascript复制docker volume prune
具名挂载和匿名挂载
指定路径挂载
上面的例子中我们用的都是指定路径挂载,就是即配置宿主机路径,又配置了容器路径;
代码语言:javascript复制docker run -d -v 主机目录:容器目录 tomcat
具名挂载
挂载到指定名称的目录;
代码语言:javascript复制# /xxx 是目录, xxx是卷名,没有斜杆的就是卷名
docker run -d -v 卷名:容器目录 tomcat
# 查找卷名所在的目录
docker volume inspect 卷名
光说无益,测试一下,先创建容器并且挂载好目录
代码语言:javascript复制docker run -d --name my_tomcat -v my_folder:/data/my_folder tomcat
使用 inspect 命令查看容器信息
代码语言:javascript复制docker inspect my_tomcat
在打印信息中找到 Mounts 项,其中Source的目录就是宿主机的目录;Destination的目录是挂载的容器目录;
代码语言:javascript复制"Mounts": [
{
"Type": "volume",
"Name": "my_folder",
"Source": "/var/lib/docker/volumes/my_folder/_data",
"Destination": "/data/my_folder",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]
接着进入容器
代码语言:javascript复制docker exec -it my_tomcat /bin/bash
# 在容器内也已经创建好了这个目录
root@ef94ff8928a1:/data/my_folder# pwd
/data/my_folder
匿名挂载
匿名挂载就是只有容器目录,没有宿主机的目录,所以生成出来的目录是一个长长的加密字符串,一般情况下不建议使用匿名挂载;加密字符串会导致不易查找;
代码语言:javascript复制docker run -d -v 容器目录 tomcat
来,测试一下,先创建容器并且挂载好目录
代码语言:javascript复制docker run -d --name my_tomcat_2 -v /my_folder_2 tomcat
使用 inspect 命令查看容器信息
代码语言:javascript复制docker inspect my_tomcat_2
在打印信息中找到 Mounts
项,其中Source
的目录就是宿主机的目录;Destination
的目录是挂载的容器目录
"Mounts": [
{
"Type": "volume",
"Name": "df4c649772a5ae65716de8ede0607d0776f8c1e2eda1d87b3ec9eaf011b43616",
"Source": "/var/lib/docker/volumes/df4c649772a5ae65716de8ede0607d0776f8c1e2eda1d87b3ec9eaf011b43616/_data",
"Destination": "/my_folder_2",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
容器与容器之间的数据共享 --volumes-from
有这么一个场景,我们需要容器A和容器B实现数据共享,就是在A容器上修改的内容我希望能在B容器上看到,那么这个功能应该要怎么做到呢?那么这时候就可以使用数据卷容器功能,数据卷容器还可以实现多个容器之间的数据同步功能,不只是2个容器共享;
1、先创建第一个容器centos_1,并将/data/centos目录挂载到宿主机上,宿主机和容器的目录都是/data/centos;
代码语言:javascript复制docker run -it --name centos_1 -v /data/centos:/data/centos centos /bin/bash
2、创建第二个容器并且将其绑定到第一个容器;--volumes-from centos_1
选项就是将当前容器的挂载目录绑定到 centos_1
容器上,从而实现了个容器的数据同步;
docker run -it --name centos_2 --volumes-from centos_1 centos /bin/bash
3、现在我们在创建第三个容器,将其绑定到第二个容器centos_2上
代码语言:javascript复制docker run -it --name centos_3 --volumes-from centos_2 centos /bin/bash
接下来,我们在每个容器里面的/data/centos目录里面都创建一个文件
- 在宿主机的/data/centos目录里面创建了main.java文件
- 在centos_1容器的/data/centos目录里面创建了centos_1.java文件
- 在centos_2容器的/data/centos目录里面创建了centos_2.java文件
- 在centos_3容器的/data/centos目录里面创建了centos_3.java文件
最后在面四个环境中的/data/centos目录执行ls命令,都能看到所有容器创建的文件,这样我们就实现了各个容器之间的数据同步;
代码语言:javascript复制[root@259efdc362b4 centos]# ls
centos_1.java centos_2.java centos_3.java main.java