#夏日挑战赛#Docker容器实战:数据存储 原创 精华

西岸Alex
发布于 2022-7-7 19:26
浏览
0收藏

[本文正在参加星光计划3.0–夏日挑战赛] https://ost.51cto.com/posts/13641#comment

 

存储对于业务的重要性不言而喻,而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 root     72 Jun  4 07:26 769dcd7a0fc4aa2630ca413734f58dfcb08ef2a1e2ca6211e3ff27c61d52c6ab
drwx--x---. 4 root root     72 Jun  4 20:53 8a88a2fa03f6b0b88e8b29c5803741c75dbb881cb3204a0d04b6ffb7cfe7983d
drwx--x---. 4 root root     72 Jun  4 07:26 8eb1a983b5682b12a8aedb4c73e0c57ee654ea41017b0c6d59dbe9f723173ff8
drwx--x---. 3 root root     47 Jun  4 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 
DRIVER    VOLUME NAME
local     myvolume

 

也可以使用 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=/data  nginx: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 exec -it nginx  touch /data/test.txt


然后,查看宿主机上volume目录情况,可看到文件已保存在该目录中。现在,我们可以很方便的对数据进行拷贝或修改了。

$ ls -l /var/lib/docker/volumes/myvolume/_data/    
total 0
-rw-r--r--. 1 root root 0 Jun  6 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 --mount  type=bind,source=/data/nginx target=/data  nginx:1.20-alpine


-v 示例

$ docker run -d --name nginx -v /data/nginx:/data  nginx: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=/data  nginx:1.20-alpine


--tmpfs选项

$ docker run -d --name nginx --tmpfs /data  nginx:1.20-alpine


查看容器信息,可看到该目录显示的类型为tmpfs,证明挂载成功。

$ docker container inspect nginx
......
        "Mounts": [
            {
                "Type": "tmpfs",
                "Source": "",
                "Destination": "/data",
......

 

我们试着在容器挂载目录中写入一个文件

$ docker exec -it nginx  touch /data/test.txt

$ docker exec -it nginx  ls -l /data
total 0
-rw-r--r--    1 root     root             0 Jun  9 08:01 test.txt

 

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

$ docker stop nginx
$ docker start nginx

$ docker exec -it nginx  ls -l /data
total 0

 

 

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
标签
已于2022-7-7 19:30:25修改
2
收藏
回复
举报
回复
    相关推荐