本章概述
- 数据类型
- 数据卷(data volume)
- 数据卷容器
前言
如果正在运行中的容器修如果生成了新的数据或者修改了现有的一个已经存在的文件内容,那么新产生的数据将会被复制到读写层进行持久化保存,这个读写层也就是容器的工作目录,此即“写时复制(COW) copy on write”机制。
如下图是将对根的数据写入到了容器的可写层,但是把/data 中的数据写入到了一个另外的 volume 中用于数据持久化。
5.1 数据类型
Docker 的镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中。如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录。
目前 Docker 的数据类型分为两种:
1、数据卷(data volume),数据卷类似于挂载的一块磁盘,数据容器是将数据保存在一个容器上。数据卷又分为docker管理的数据卷以及指定挂载的数据卷(绑定挂载卷)。
(1)docker管理的数据卷是指在创建容器时没有指定挂载数据卷,docker会将目录挂载到指定的目录下,该目录由docker自动生成。
(2)指定挂载的数据卷是指创建容器时手动指定挂载的数据卷,该数据卷需要指定宿主机以及容器内挂载的数据卷。
2、数据卷容器(Data volume container), 数据卷容器是将宿主机的目录挂载至一个专门的数据卷容器,然后让其他容器通过数据卷容器读写宿主机的数据。
5.2 数据卷(data volume)
数据卷实际上就是宿主机上的目录或者是文件,可以被直接 mount 到容器当中使用。
实际生产环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性。
如下图:
左侧是无状态的 http 请求服务,右侧为有状态。
下层为不需要存储的服务,上层为需要存储的部分服务。
5.2.1 数据卷的特点及使用场景
1、特点
(1)数据卷是宿主机的目录或者文件,并且可以在多个容器之间共同使用。
(2)在宿主机对数据卷更改数据后会在所有容器里面会立即更新。
(3)数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。
(4)在容器里面的写入数据不会影响到镜像本身。
2、使用场景
(1)日志输出
(2)静态web页面
(3)应用配置文件
(4)多容器间目录或文件共享
5.2.2 docker管理的数据卷
1、容器中的数据保存在哪?
运行一个nginx容器,查看其存储信息
root@docker_server01:~# docker run -it -d -p 8088:80 nginx:1.18.0
root@docker_server01:~# docker inspect 057612785cd7 #查看指定容器的详细信息
参数说明:
LowerDir:image 镜像层(镜像本身,只读)
UpperDir:容器的上层(读写)
MergedDir:容器的文件系统,使用 Union FS(联合文件系统)将 lowerdir 和upperdir 合并给容器使用。
WorkDir:容器在 宿主机的工作目录
容器的文件系统是MergedDir,因此容器中的数据保存在MergedDir目录中,该目录都是由docker默认生成的,即docker管理的数据卷
查看MergedDir中的数据,可以看到nginx容器中的配置文件
知识延伸:
1、UpperDir 路径保存容器新增数据
其中UpperDir 的路径/var/lib/docker/overlay2/3452b51ffe53557933032214e7c63437642289be2ab3992c41d5247dbdcfbf85/diff是指差异数据,容器中产生的差异数据都会保存在该目录下。容器创建以后增加的数据都会保存在该目录下
2、容器删除后,容器内的数据会随之删除,但容器挂载到宿主机数据卷内的数据会保留下来
5.2.3 指定挂载的数据卷
5.2.3.1 挂载宿主机目录到容器
将宿主机目录以数据卷的方式挂载到容器内,比如把宿主机上应用的代码文件挂载到tomcat的代码目录下,此方式适用于小型 web 站点。
1、挂载目录到容器并验证
(1)在宿主机创建文件
root@docker_server01:~# mkdir -p /data/testapp
root@docker_server01:~# echo "testapp web" > /data/testapp/index.html
root@docker_server01:~# cat /data/testapp/index.html
(2)启动tomcat容器,将宿主机文件挂载到容器内
root@docker_server01:~# docker run -it -d -p 8081:8080 -v /data/testapp/:/data/tomcat/webapps/testapp tomcat-web:app1
注意:启动tomcat容器使用的是tomcat-web:app1镜像,tomcat中web页面的默认路径是/data/tomcat/webapps
(3)进入容器查看文件
(4)访问tomcat web页面,查看数据
(5)修改宿主机文件,再次访问tomcat web页面
root@docker_server01:~# echo "testapp web v2" > /data/testapp/index.html
知识延伸:
(1)为挂载目录设置权限
在挂载宿主机目录时,可以为目录设置读写权限,如下所示,ro是指容器内的目录为只读权限
root@docker_server01:~# docker run -it -d -p 8081:8080 -v /data/testapp/:/data/tomcat/webapps/testapp:ro tomcat-web:app1
进入容器,尝试在挂载目录下写入数据,提示文件为只读
root@docker_server01:~# docker exec -it 630275bdc859 bash
[root@630275bdc859 /]# echo "testweb app v3" > /data/tomcat/webapps/testapp/index.html #向该文件写入数据,会提示该文件是只读文件,无法写入
(2)宿主机上的同一个目录或文件可以挂载到多个容器内
2、删除容器验证数据是否丢失
(1)删除tomcat容器
(2)查看数据卷数据
5.2.3.2 挂载宿主机文件到容器
文件挂载用于很少更改文件内容的场景,比如 把nginx 的配置文件、tomcat 的配置文件挂载到容器内。
1、创建挂载的文件(这里修改server.xml,用来演示)
root@docker_server01:/data# mkdir -p /data/tomcat/conf && cd /apps/tomcat/conf/
vim server.xml # 将autoDeploy由false改为true
<Host name="localhost" appBase="/data/tomcat/webapps" unpackWARs="false" autoDeploy="true">
存在问题:
容器中tomcat是由www用户启用的,因此需要将server.xml属主修改为www用户,但是宿主机上没有www用户,无法将文件的属主设置为www用户。
解决方法:
查看www用户的id,把server.xml的属组修改为www的用户id。
(1)先进入容器查看容器默认server.xml文件属主的用户id,这里server.xml的属主www,id为2023
(2)在宿主机修改server.xml的属主和属组(由于宿主机上没有www用户,因此无法将server.xml文件的属主修改为www用户,但可以将文件的属主修改为用户id,这样也可以生效)
chown -R 2023.2023 /data/tomcat
2、启动容器
root@docker_server01:/data/tomcat/conf# docker run -it -d -p 8082:8080 -v /data/tomcat/conf/server.xml:/apps/tomcat/conf/server.xml:ro tomcat-web:app1
注意:tomcat-web:app1镜像中tomcat的配置文件目录为/apps/tomcat/conf,这里的ro是指将server.xml设置为只读
3、进入容器查看配置文件,配置文件内容和宿主机上一致,挂载成功
4、尝试向配置文件写入数据,提示配置文件是只读文件
5、访问web页面 172.31.7.150:8082/myapp(该镜像web页面为/data/tomcat/webapps/myapp)
5.2.3.3 如何一次挂载多个目录
多个目录可以位于不同目录下
1、创建挂载的目录
root@docker_server01:~# mkdir /data/magedu
root@docker_server01:~# echo magedu > /data/magedu/index.html
2、启动容器,挂载多个目录
root@docker_server01:~# docker run -it -d -p 8083:8080 -v /data/testapp/:/data/tomcat/webapps/testapp -v /data/magedu/:/data/tomcat/webapps/magedu tomcat-web:app1
3、访问web页面,进行验证
浏览器访问testapp页面: http://172.31.7.150:8083/testapp/
浏览器访问magedu页面:http://172.31.7.150:8083/magedu/
5.3 数据卷容器
数据卷容器功能是可以让数据在多个 docker 容器之间共享,即可以让 B 容器访问 A 容器的内容,而容器 C 也可以访问 A 容器的内容,即先要创建一个后台运行的容器作为 Server,用于卷提供,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为 client 端:
5.3.1 启动一个数据卷容器
启动一个数据卷容器,并挂载宿主机的数据目录:
将宿主机的server.xml配置文件和/data/testapp目录下的index.html,分别挂载到卷容器 server端,然后通过 server 端共享给 client 端使用。并且server.xml设置为只读权限
root@docker_server01:~# docker run -it -d --name volume-server -v /data/testapp/:/data/tomcat/webapps/testapp -v /data/tomcat/conf/server.xml:/apps/tomcat/conf/server.xml:ro tomcat-web:app1
注意:创建容器时,一定要给容器指定容器名称,这样其他容器就可以根据该容器名称共享卷server容器挂载的数据(因为容器id会发生变化,因此指定容器名称比较方便)
5.3.2 启动两个client容器
root@docker_server01:~# docker run -it -d --name web1 -p 8801:8080 --volumes-from volume-server tomcat-web:app1
root@docker_server01:~# docker run -it -d --name web2 -p 8802:8080 --volumes-from volume-server tomcat-web:app1
5.2.3 验证
1、进入client容器,查看server.xml文件权限,该文件为只读
2、浏览器访问web页面,都可以正常访问
5.2.4 停止数据卷容器,测试创建新容器
1、停止数据卷容器
root@docker_server01:~# docker stop volume-server
2、创建新容器,可以正常创建
root@docker_server01:~# docker run -it -d --name web3 -p 8803:8080 --volumes-from volume-server tomcat-web:app1
3、已经根据数据卷容器创建的容器可以正常访问
总结:
停止数据卷容器
(1)根据数据卷容器已经创建的容器不受影响
(2)可以根据数据卷容器正常新建容器
5.2.4 删除数据卷容器,测试创建新容器
1、删除数据卷容器
root@docker_server01:~# docker rm -f volume-server
2、创建新容器报错,提示没有数据卷容器
root@docker_server01:~# docker run -it -d --name web4 -p 8804:8080 --volumes-from volume-server tomcat-web:app1
3、已经根据数据卷容器创建的容器可以正常访问
总结:
删除卷server容器
(1)根据数据卷容器已经创建的容器不受影响
(2)无法根据数据卷容器新建容器
文章评论