
一、容器存储概述
1.容器和层
容器和镜像最大的区别在于顶层中的可写层,所有在容器中的数据写入和修改都会直接存储到这个可写层中。通俗的说,当容器被删除时,可写层中的数据就会丢失。虽然每个容器都有不同的可写层,但是容器底层的镜像都是可以同时共享的。

2. 主流的存储驱动
在容器的设计和使用时,在容器可写层中写入的数据是非常少的。在实际的生产环境中,大部分数据是必须要具备持久化保存的能力,所以在容器中引入了多种存储驱动来解决可写层数据的易失性。
3. Copy-on-Write
CoW(Copy-on-Write,写时复制),数据只读共享,只有在写入时才复制。多个使用者先共享同一份原始数据(数据只读),当有人需要修改数据时,先把原始数据拷贝一份给使用者,让其修改拷贝后的副本,原始数据保持不变,这样不会影响其它使用者。
4. Storage Driver
Storage Driver管理镜像层和容器层,Storage Driver处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户提供多层数据合并后的统一视图。所有Storage Driver都使用可堆叠图像层和写时复制(CoW)策略。
Storage Driver类型
[Step1] 查看当前系统中的Storage Driver。
[root@redhat ~]# docker info
二、主机与容器间数据共享
1. 存储方式
docker主机与容器间中持久化数据一般采用两种存储方式
volume:将Host上的数据copy到容器的volume中(使用docker cp命令在容器与Host之间复制数据)
bind mount:将Host上的目录或文件mount到容器中

2. volume
volume由Docker管理,将特定目录挂载给容器使用。Docker会在指定路径下为每个volume生成一个目录作为mount源。如果没有手动指定路径,默认会挂载在“/var/lib/docker/volumes”。
[Step1]: 基于kylinsp3镜像创建一个容器volume01,并为其分配一个volume卷。
[root@redhat ~]# docker run -d --name volume01 -v /mnt kylinsp3:latest /sbin/init[Step2] 查看Docker为volume01容器所分配的卷位置。
[root@redhat ~]# docker inspect volume01 | grep Source
[Step3] 往volume卷中写入内容。
[root@redhat ~]# echo "Hello World!" > /var/lib/docker/volumes/cee74954431bf64e0aac09765fbb61fe0c9536d8eff4e69e35940103ffbaced9/_data/hello.txt[Step4] 连接容器volume01,能够查看到hello.txt文件内容,同时新建文件。
[root@redhat ~]# docker exec -it volume01 /bin/bash
[root@ffefeb27f776 /]# cat /mnt/hello.txt
[root@ffefeb27f776 /]# echo "2026-1-5" > /mnt/time.txt
[Step4] 验证:能够在volume目录下查看刚刚创建的文件及其内容。
[root@redhat ~]# ll /var/lib/docker/volumes/cee74954431bf64e0aac09765fbb61fe0c9536d8eff4e69e35940103ffbaced9/_data/
[root@redhat ~]# cat /var/lib/docker/volumes/cee74954431bf64e0aac09765fbb61fe0c9536d8eff4e69e35940103ffbaced9/_data/time.txt
[Step5]: 删除掉该容器后,可以看到数据仍然存在,可持久化存储。
[root@redhat ~]# docker rm -f volume01
[root@redhat ~]# ll /var/lib/docker/volumes/cee74954431bf64e0aac09765fbb61fe0c9536d8eff4e69e35940103ffbaced9/_data/
3. bind mount
bind mount是将宿主机上已有的目录或文件mount到容器中。

[Step1] 创建一个新的目录“/volume”,在目录中新建一个txt文件。
[root@redhat ~]# mkdir /volume
[root@redhat ~]# echo "Hello World!" > /volume/hello.txt[Step2] 基于kylinsp3镜像创建一个容器bind01,将/volume目录挂载到容器中。随后登录容器,能够读取目录中内容。
[root@redhat ~]# docker run -d --name bind01 -v /volume:/mnt kylinsp3:latest /sbin/init
[root@redhat ~]# docker exec -it bind01 /bin/bash
[root@ee15a5653b22 /]# ll /mnt/
[root@ee15a5653b22 /]# cat /mnt/hello.txt
[Step3] 删除掉该容器后,可以看到数据仍然存在,可持久化存储。
[root@redhat ~]# docker rm -f bind01
[root@redhat ~]# ll /volume/
4. docker cp
[Step1] 基于kylinsp3镜像创建一个容器docker_cp。
[root@redhat ~]# docker run -d --name docker_cp kylinsp3:latest /sbin/init[Step2] 在本地新建一个文件,复制到容器docker_cp。
[root@redhat ~]# echo "docker_cp" > docker_cp.txt
[root@redhat ~]# docker cp docker_cp.txt docker_cp:/mnt
[Step3] docker cp也支持将容器文件复制到宿主机,将docker_cp中的hostname文件复制宿主机当前目录。
[root@redhat ~]# docker cp docker_cp:/etc/hostname .
[root@redhat ~]# cat hostname
三、容器与容器间数据共享
1. 挂载同一目录实现数据共享
多个容器通过“-v”参数挂载到同一个物理位置实现数据共享。
[Step1] 创建一个新的目录“/volume_contianer”,在目录中新建一个txt文件。
[root@redhat ~]# mkdir /volume_contianer
[root@redhat ~]# echo "docker file" > /volume_contianer/docker.txt[Step2] 基于kylinsp3镜像创建一个容器ky01,将/volume_contianer目录挂载到容器中。登录容器,能够读取目录中内容,随后创建一个新文件ky01.txt。
[root@redhat ~]# docker run -d --name ky01 -v /volume_contianer:/mnt kylinsp3:latest /sbin/init
[root@redhat ~]# docker exec -it ky01 /bin/bash
[root@de1949837e00 /]# echo "ky01 file" > /mnt/ky01.txt[Step3] 基于kylinsp3镜像创建一个容器ky02,将/volume_contianer目录挂载到容器中。登录容器,能够读取目录中内容。
[root@redhat ~]# docker run -d --name ky02 -v /volume_contianer:/mnt kylinsp3:latest /sbin/init
[root@redhat ~]# docker exec -it ky02 /bin/bash
[root@ab9bc99fe611 /]# ls /mnt/
[root@ab9bc99fe611 /]# cat /mnt/docker.txt
[root@ab9bc99fe611 /]# cat /mnt/ky01.txt
2. 容器卷实现数据共享
容器卷:将一个容器作为数据卷,然后其它容器引用这个容器中的数据。
[Step1] 创建一个新的目录“/docker_volume”,在目录中新建一个txt文件并写入内容。
[root@redhat ~]# mkdir /docker_volume
[root@redhat ~]# echo "Hello World!" > /volume01/hello.txt[Step2] 基于kylinsp3镜像创建一个容器卷docker_volume,将“/docker_volume”挂载到容器的/mnt目录。
[root@redhat ~]# docker run -d --name docker_volume -v /docker_volume:/mnt kylinsp3:latest /sbin/init[Step3] 基于kylinsp3镜像创建两个容器分别为kylin01和kylin02,将“/docker_volume”挂载到容器的/mnt目录。
[root@redhat ~]# docker run -d --name kylin01 --volumes-from docker_volume kylinsp3:latest /sbin/init
[root@redhat ~]# docker run -d --name kylin02 --volumes-from docker_volume kylinsp3:latest /sbin/init[Step4] 分别查看docker_volume、kylin01和kylin03三个容器的挂载信息,可以看到三个容器的卷挂载信息都是一致的
[root@redhat ~]# docker inspect docker_volume | grep Source
[root@redhat ~]# docker inspect kylin01 | grep Source
[root@redhat ~]# docker inspect kylin02 | grep Source
[Step5] 验证:登录容器kylin01,能够读取文件内容。
[root@redhat ~]# docker exec -it kylin01 /bin/bash
[Step6] 验证:登录容器kylin01,新建文件kylin01并写入内容。
[root@17e8100decaf /]# echo "kylin01" > /mnt/kylin01.txt[Step7] 验证:登录容器kylin02,能够读取文件内容和新建文件。
[root@redhat ~]# docker exec -it kylin02 /bin/bash
[root@ac737fc2cf39 /]# cat /mnt/hello.txt
[root@ac737fc2cf39 /]# cat /mnt/kylin01.txt
[root@ac737fc2cf39 /]# echo "kylin02" > /mnt/kylin02.txt
