3

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

 1 year ago
source link: https://blog.51cto.com/u_14065119/5449242
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

存储对于业务的重要性不言而喻,而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
$ 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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK