Docker容器实战十一(数据存储)

别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述Docker容器实战十一:数据存储相关的知识,希望能为你提供帮助。
存储对于业务的重要性不言而喻,而Docker作为最受欢迎的容器产品,本身也提供了非常优秀的数据存储机制。
Docker的存储可分为容器存储  、持久化存储和临时存储三种方式,它们之间各有特点并分别适用于不同的场景,本文将其对进行详细介绍,相信读者在学习后能够更好的应用。


一.  容器存储  在前面的文章中,我们讲到了镜像与容器的原理。其中镜像层为只读层,而容器层则为可写层,对于容器内文件的修改将会被保存在可写层中。这种分层架构的应用,使得容器的运作变得简洁而高效。

Docker容器实战十一(数据存储)

文章图片



将这些层的内容合并为一个统一的视图,这种技术被称为联合文件系统(UnionFS),这是一种分层、轻量级并且高性能的文件系统。而这些能力的实现源于底层存储驱动的支持,目前Docker支持的驱动包括overlay2、devicemapper、aufs等,其中overlay2为默认的存储驱动。
$ docker info |grep -A 2 Storage
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true

当使用overlay2驱动时,镜像层与容器层的文件默认保存在/var/lib/docker/overlay2目录内,该目录由Docker程序进行管理。每一个层对应着这里的一个目录,查看目录即可看到该层的内容文件。?
$ ls -l /var/lib/docker/overlay2/
total 0
drwx--x---. 4 root root72 Jun4 07:26 769dcd7a0fc4aa2630ca413734f58dfcb08ef2a1e2ca6211e3ff27c61d52c6ab
drwx--x---. 4 root root72 Jun4 20:53 8a88a2fa03f6b0b88e8b29c5803741c75dbb881cb3204a0d04b6ffb7cfe7983d
drwx--x---. 4 root root72 Jun4 07:26 8eb1a983b5682b12a8aedb4c73e0c57ee654ea41017b0c6d59dbe9f723173ff8
drwx--x---. 3 root root47 Jun4 07:26 b150ab0468a97ca2b17ad14d68134ce1eb5c7b71e33e6aab2c36d418796d5d4f
......

当容器被删除时,我们会看到该层的目录也随着删除。这种方式对于无状态的应用非常合适,如Web应用或者工具软件等。


二.  持久化存储  在实际的生产环境中,除了无状态的应用外,往往也会有着需要数据持久化的应用,如数据库、业务系统等。对于这类应用,容器层的存储方式显然并不适用,我们可以通过持久化存储来支持。
Docker为容器的数据持久化存储提供了两种模式:volumes(卷)和bind mounts(绑定挂载)。
  • volumes
使用volumes的方式很简单,先创建?volume,然后在启动容器时进行挂载。
现在,我们来验证一下。
1. 使用docker volume  create命令创建volume,此处名称为myvolume。这里使用Docker内置的local驱动创建一个本地volume,该资源只能被本机上的容器使用。
$ docker volume create -d local myvolume
myvolume

2. 创建完成后,可通过docker volume ls 命令查看列表信息。
$ docker volume ls
DRIVERVOLUME NAME
localmyvolume

也可以使用 docker volume inspect查看该资源的详情。
$ docker volume inspect myvolume
[

"CreatedAt": "2022-06-05T23:22:58-04:00",
"Driver": "local",
"Labels": ,
"Mountpoint": "/var/lib/docker/volumes/myvolume/_data",
"Name": "myvolume",
"Options": ,
"Scope": "local"

volume的文件存放在主机内特定的路径 ,位于 /var/lib/docker/volumes/< volume_name> 目录中,这点我们可在inspect命令的输出中看到。
3. 启动容器并挂载该volume,挂载的选项有--mount和 -v ,通常而言--mount语法更加明确和详细。
如:
$ docker run -d --name nginx --mount type=volume,source=myvolume,target=/datanginx:1.20-alpine

注释:type指定挂载类型;source和target指定源和挂载路径。


而-v 则是将相关选项组成到一个字段中,上面命令等同于:
$ docker run -d --name nginx -v myvolume:/data nginx:1.20-alpine

有意思的是,即使系统中没有这个volume, 命令依然可以运行,此时Docker会创建一个同名的资源。
你甚至可以不指定名称,如下:
$ docker run -d --name nginx -v /data nginx:1.20-alpine

此时,容器会生成一个随机名称的volume。


4. 在启动容器后,我们试着往该容器内的挂载目录写入数据来验证volume的使用。
【Docker容器实战十一(数据存储)】先在该目录中创建一个文件
$ docker exec -it nginxtouch /data/test.txt

然后,查看宿主机上volume目录情况,可看到文件已保存在该目录中。现在,我们可以很方便的对数据进行拷贝或修改了。
$ ls -l /var/lib/docker/volumes/myvolume/_data/
total 0
-rw-r--r--. 1 root root 0 Jun6 04:28 test.txt

使用volumes方式挂载时,如果容器中的挂载目录已经存在文件,那么会被同步到volume中。这给我们带来了很大的便利性,我们可以不用手动去把文件从容器中拷贝出来。
当该容器被删除时volume依然会存在,它可以被重新挂载到其他容器中,这保证了存储与容器的解耦,实现了我们需要的数据持久化功能。
如果需要删除volume,可以先删除挂载容器,然后使用docker volume rm < volume_name>   命令进行删除,删除后该volume相关的目录将会被自动清理掉。
$ docker volume rm myvolume

volumes除了支持挂载本机的目录外,也支持挂载到远程目录,如NFS服务器等。下面是NFS类型的volume创建示例,当创建完成后,我们即可以按照上面的方式将其挂载到容器中(主机需安装NFS Client)。
$ docker volume create -d local \\
--opt type=nfs \\
--opt o=addr=[nfs_address] \\
--opt device=:[nfs-directory] \\
[volume-name]

  • bind mounts
bind mounts是将宿主机上已存在的目录或文件挂载到容器,与volumes方式不同的是bind mounts需要指定绝对路径。
例如,我们将宿主机的/data/nginx目录,挂载到容器中的/data目录中。
--mount  示例
$ docker run -d --name nginx --mounttype=bind,source=/data/nginx target=/datanginx:1.20-alpine

-v 示例
$ docker run -d --name nginx -v /data/nginx:/datanginx:1.20-alpine

bind mount的方式与Linux mount类似,挂载后容器中相关目录的内容将会被隐藏,此时只会展示bind mount目录的内容,这点与volume明显不同。
当容器被删除时,对bind mount目录不会有影响,此时该目录依然保存在宿主机中,可用于其他容器的绑定。
除了挂载目录外,bind mount还支持对单个文件的挂载,如下  :
$ docker run -d --name nginx -v /data/nginx/nginx.conf:/etc/nginx/nginx.conf nginx:1.20-alpine

使用bind mount 挂载的目录,无法在docker命令行进行管理,所以通常建议优先使用volumes模式。
?
三.  临时存储  在容器保存文件时,除了容器层存储以及持久化的存储外,还有第三种方式:tmpfs mounts。
与持久化存储相反,tmpfs mount是临时性的,存储内容会保存在内存中。当容器停止时,tmpfs的挂载将被移除,写入的文件也不会存在。这适用于保存在容器运行过程产生的敏感文件,你不希望它们保存在主机磁盘中。
支持tmpfs mounts 挂载的选项有 --mount 和 --tmpfs,它们的用法分别如下:
--mount选项
docker run -d --name nginx --mount type=tmpfs,target=/datanginx:1.20-alpine

--tmpfs选项
docker run -d --name nginx --tmpfs /datanginx:1.20-alpine

查看容器信息,可看到该目录显示的类型为tmpfs,证明挂载成功。
$ docker container inspect nginx
......
"Mounts": [

"Type": "tmpfs",
"Source": "",
"Destination": "/data",
......

我们试着在容器挂载目录中写入一个文件
$ docker exec -it nginxtouch /data/test.txt

$ docker exec -it nginxls -l /data
total 0
-rw-r--r--1 rootroot0 Jun9 08:01 test.txt

当容器停止后,该挂载的内存空间将会被释放,此时重新启动容器将分配新的空间。
$ docker stop nginx
$ docker start nginx

$ docker exec -it nginxls -l /data
total 0



 
  专注于Devops、SRE、运维开发等技术分享,扫码关注公众号,获取更多精彩内容!
Docker容器实战十一(数据存储)

文章图片


    推荐阅读