Docker容器实战十一:数据存储

Posted 运维老兵Alex

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker容器实战十一:数据存储相关的知识,希望对你有一定的参考价值。

存储对于业务的重要性不言而喻,而Docker作为最受欢迎的容器产品,本身也提供了非常优秀的数据存储机制。

Docker的存储可分为容器存储 、持久化存储和临时存储三种方式,它们之间各有特点并分别适用于不同的场景,本文将其对进行详细介绍,相信读者在学习后能够更好的应用。


一. 容器存储 

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

Docker容器实战十一:数据存储_devops


将这些层的内容合并为一个统一的视图,这种技术被称为联合文件系统(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


 


 专注于Devops、SRE、运维开发等技术分享,扫码关注公众号,获取更多精彩内容!

Docker容器实战十一:数据存储_devops_02

以上是关于Docker容器实战十一:数据存储的主要内容,如果未能解决你的问题,请参考以下文章

Docker数据卷管理

docker 数据管理

docker mysql 容器 数据库文件怎么娴宿主机器上

docker mysql 容器 数据库文件怎么娴宿主机器上

有啥好的办法解决 docker 容器与宿主机时间不同步的问题

7.Docker技术入门与实战 --- 端口映射与容器互联