前言 Docker 卷与持久化数据存储
创建数据卷
1 | [root@imwl-124 ~]# docker volume create myvolume |
查看数据卷
1 | [root@imwl-124 ~]# docker volume ls |
使用数据卷
1 | docker run -d --name=nginx --mount source=myvolume,target=/usr/share/nginx/html nginx |
其中创建 + 使用 等同于
docker run -d --name=nginx-volume -v /usr/share/nginx/html nginx
旧容器删除,数据卷并不会删除
删除数据卷
1 | docker volume rm myvolume |
容器与容器之间数据共享
使用 volumes-from 参数可以在启动新的容器时来挂载已经存在的容器的卷,volumes-from 参数后面跟已经启动的容器名称1
2
3
4
5docker volume create log-vol
docker run --mount source=log-vol,target=/tmp/log --name=log-producer -it busybox
docker run -it --name consumer --volumes-from log-producer busybox
主机与容器之间数据共享
-v HOST_PATH:CONTIANAER_PATH1
docker run -v /data:/usr/local/data -it busybox
原理
1 | [root@imwl-124 ~]# ls -l /var/lib/docker/volumes |
Docker 卷的实现原理是在主机的 /var/lib/docker/volumes 目录下,根据卷的名称创建相应的目录,然后在每个卷的目录下创建 _data 目录,在容器启动时如果使用 --mount 参数,Docker 会把主机上的目录直接映射到容器的指定目录下,实现数据持久化
分类
AUFS: 现在很少使用Devicemapper: 常用在Red Hat或CentOS系统中OverlayFS:Docker目前推荐选择
Devicemapper
Docker 的 Devicemapper 模式有两种:
loop-lvm: 主要用来开发和测试使用direct-lvm: 推荐在生产环境中使用
direct-lvm
当前生产环境 使用的 模式
loop-lvm 仅配置 “storage-driver”: “devicemapper”, 不配置 “storage-opts”1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@test-196 ~]# cat /etc/docker/daemon.json
{
"bip": "172.27.0.1/16",
"fixed-cidr": "172.27.0.0/16",
"insecure-registries": ["127.0.0.1/8"],
"storage-driver": "devicemapper",
"exec-opts": ["native.cgroupdriver=systemd"],
"storage-opts": [
"dm.basesize=20G",
"dm.thinpooldev=/dev/mapper/docker-thinpool",
"dm.use_deferred_removal=true",
"dm.use_deferred_deletion=true"
]
}
查看1
2
3
4
5
6
7
8
9[root@test-196 ~]# docker info |grep Driver
Storage Driver: devicemapper # 使用 devicemapper
Logging Driver: json-file
Cgroup Driver: systemd
[root@test-196 ~]# docker info |grep Pool
Pool Name: docker-thinpool # direct-lvm 模式已经配置成功
Pool Blocksize: 524.3kB
Thin Pool Minimum Free Space: 51GB
Devicemapper 原理
Devicemapper 是一种映射块设备的技术框架, 提供了一种将物理块设备映射到虚拟块设备的机制。
Devicemapper 将主要的工作部分分为 用户空间 和 内核空间
用户空间负责配置具体的设备映射策略与相关的内核空间控制逻辑,例如逻辑设备 dm-a 如何与物理设备 sda 相关联,怎么建立逻辑设备和物理设备的映射关系等。
内核空间则负责用户空间配置的关联关系实现,例如当 IO 请求到达虚拟设备 dm-a 时,内核空间负责接管 IO 请求,然后处理和过滤这些 IO 请求并转发到具体的物理设备 sda 上。
映射设备 通过 映射表 关联到具体的 物理目标设备 。事实上,映射设备不仅可以通过映射表关联到物理目标设备,也可以关联到虚拟目标设备,然后虚拟目标设备再通过映射表关联到物理目标设备。

瘦供给(Thin Provisioning) : 需要多少磁盘空间,存储驱动就帮我们分配多少磁盘空间
Docker 使用了瘦供给的 snapshot 技术, Docker 将镜像和容器的文件存储在瘦供给池(thinpool )中,并将这些内容挂载在 /var/lib/docker/devicemapper/ 目录下。
1 | [root@test-249 devicemapper]# pwd |

这个 Ubuntu 镜像一共有四层,每一层镜像都是下一层的快照,镜像的最底层是基础设备的快照。当容器运行时,容器是基于镜像的快照。Devicemapper 实现镜像分层的根本原理就是快照
快照是数据在某一个时间点的存储状态。快照的主要作用是对数据进行备份,当存储设备发生故障时,可以使用已经备份的快照将数据恢复到某一个时间点,而 Docker 中的数据分层存储也是基于快照实现的。
overlay2
要想使用 overlay2,Docker版本必须高于17.06.02`。
如果你的操作系统是 RHEL 或 CentOS,Linux 内核版本必须使用 3.10.0-514 或者更高版本,其他 Linux 发行版的内核版本必须高于 4.0(例如 Ubuntu 或 Debian),可以使用 uname -a 查看当前系统的内核版本。
overlay2 最好搭配 xfs 文件系统使用,并且使用 xfs 作为底层文件系统时,d_type 必须开启,可以使用以下命令验证 d_type 是否开启:
1 | [imwl@imwl-u ~]$ xfs_info /var/lib/docker | grep ftype |
ftype=1 时,表示 d_type 已经开启。 sudo mkfs.xfs -f -n ftype=1 /path/to/disk
示例
挂载 /var/lib/docker 到 /dev/vdb11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 500G 0 disk
└─vda1 253:1 0 500G 0 part /
vdb 253:16 0 500G 0 disk
└─vdb1 253:17 0 8G 0 part
$ sudo mkfs.xfs -f -n ftype=1 /dev/vdb1
$ sudo echo "/dev/vdb1 /var/lib/docker xfs defaults,pquota 0 0" >> /etc/fstab
$ sudo mount -a
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 500G 0 disk
└─vda1 253:1 0 500G 0 part /
vdb 253:16 0 500G 0 disk
└─vdb1 253:17 0 8G 0 part /var/lib/docker
$ xfs_info /var/lib/docker | grep ftype
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
使用
修改 /etc/docker/daemon.json1
2
3
4
5
6
7{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.size=20G",
"overlay2.override_kernel_check=true"
]
}
限制每个容器根目录大小为 20G
重启 docker1
$ sudo systemctl start docker
docker_info 节选
1 |
|
storage Driver 已经变为 overlay2,并且 d_type 也是 true
原理
overlay2 和 AUFS 类似,它将所有目录称之为层(layer),overlay2 的目录是镜像和容器分层的基础,而把这些层统一展现到同一的目录下的过程称为联合挂载(union mount)。overlay2 把目录的下一层叫作 lowerdir,上一层叫作 upperdir,联合挂载后的结果叫作 merged。
overlay2 将镜像层和容器层都放在单独的目录,并且有唯一 ID ,每一层仅存储发生变化的文件,最终使用联合挂载技术将容器层和镜像层的所有文件统一挂载到容器中,使得容器中看到完整的系统文件。
AUFS
配置

1
2
3{
"storage-driver": "aufs"
}
每一个目录在 AUFS 中都叫作分支,而在 Docker 中则称之为层(layer),但最终呈现给用户的则是一个普通单层的文件系统,我们把多层以单一层的方式呈现出来的过程叫作联合挂载。