docker存储卷分类与实操

定义

是什么 :存储卷就是将宿主机本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一个目录建立绑定关系,当我们在容器的这个目录下写入数据的时候,容器会将其内容直接写入宿主机与此容器建立了绑定关系的目录上。

在宿主机上的这个与容器形成绑定关系的目录称为存储卷,卷的本质是文件或者目录,它可以绕过默认的联合文件系统,直接以文件或者目录的形式存在于宿主机上。
为什么:为什么需要存储卷呢?

  • 数据丢失问题
    容器按照业务类型分为两类,第一类是无状态的,数据不需要被持久化,第二类是有状态的,数据需要被持久化。
    容器更擅长无状态应用,因为未持久化的容器根目录的生命周期和容器的生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对任何文件的修改都只存在于读写层,当容器被删除的时候,容器中的读写层也会随之消失。但实际业务中总是需要各种有状态的场景,比如MySQL,Kafka等有状态的业务。
  • 性能问题
    UnionFS对于修改删除时,一般效率非常低,对于一个对IO要求比较高的应用,如redis在实现持久化存储时,对于底层存储的性能要求较高。
  • 宿主机和容器互相访问不方便
    宿主机访问容器,或者容器访问宿主机都要通过docker cp来完成,容器很难操作。
  • 容器和容器之间互相访问不方便

分类

volume docker 管理卷

默认映射到宿主机的/var/lib/docker/volumes目录下,只需要在容器内指定容器的挂载点是什么,而被绑定宿主机下的那个目录,是由容器引擎daemon自行创建的一个空目录,或者使用一个已经存在的目录,这种方式降低了耦合关系,缺陷是用户无法指定那些使用目录,临时存储比较适合。

创建卷

volume命令操作
docker volume create

用于创建存储卷。

bash 复制代码
docker volume create [options] [volume]

-d指定驱动,默认是local

-label指定元数据

docker volume inspect

用于查看卷详细信息。

bash 复制代码
docker volume inspect [options] volume1 [volume2...]

-f指定相应个格式

docker volume ls

列出所有的卷。

bash 复制代码
docker volume ls [options]

--format指定相应格式,如json,table等

--filter过滤

-q表示仅显示名称

docker volume rm

用于删除卷,需要在容器不使用的情况下使用。

bash 复制代码
docker volume rm [options] volume1 [volume2...]

-f表示强制删除

docker volume prune

删除不使用的本地卷。

bash 复制代码
docker volume prune [options]

--filter表示过滤

-f表示不提示是否删除

-v或者--mount指定
-v参数
bash 复制代码
docker run -v name:directory[:options]

name表示卷的名称,directory表示卷映射到容器的目录,option表示选项。

当指定了一个-v参数创建容器以后,使用docker inspect就可以看到此存储卷。

--mount参数

用于完成目录映射。

bash 复制代码
--mount '<key>=<value>,<key>=<value>'

type类型表示bind,volume或者tmpfs

source对于有命名的卷来说,这是卷的名称,对于匿名的卷省略此字段

destination/dst/target表示文件或者目录挂载在容器中的路径

ro表示以只读方式挂载

dockerfile匿名卷

通过dockerfile的volume可以创建docker管理卷,也可以通过dockerfile的volume指令在镜像中创建data volume,这样只要通过改镜像创建的容器都会存在挂载点,但通过volume指令创建的挂载点无法指定主机上对应的目录,而是由docker随机生成的。

操作

docker命令创建管理卷
  • 命令创建管理卷
bash 复制代码
docker volume create 卷名
  • 查看docker管理卷
bash 复制代码
docker volume ls
  • 查看其中一个管理卷,可以看到对应的宿主机目录
bash 复制代码
docker volume inspect 卷名
  • 进入宿主机目录,可以看到容器里面的内容已经放到该目录了
bash 复制代码
cd 目录
ls -l
  • 使用docker inspect查看容器,可以看到对应的卷信息
  • 修改index.html
bash 复制代码
cd 目录
  • 通过浏览器查看
docker卷生命周期
  • -v创建管理卷,并且启动容器
bash 复制代码
docker container run --name 容器名 -d -p 80:80 -v 卷名:/usr/share/nginx/html nginx 
  • 进入卷目录,当我们将一个空白的卷挂载到一个容器上以后,容器挂载目录里的文件会自动放到宿主机对应的文件夹里。
  • 停止容器,清理容器
bash 复制代码
docker stop 容器名
docker rm 容器名
  • 进入卷目录查看对应的文件,发现没有删除,当删除卷以后,就看不见这个目录了

bind mount绑定数据卷

映射到宿主机指定路径下,在宿主机上的路径要人工指定一个特定的路径,在容器中也需要指定一个特定的路径,两个已知的路径建立联系。

创建卷

-v参数创建卷
bash 复制代码
docker run -v name:directory[:options]...

name表示宿主机的目录,directory表示卷映射到容器的目录,option是选项,如ro表示readonly只读。

--mount创建卷

--mount用于完成目录映射。

bash 复制代码
--mount '<key>=<value>,<key>=<value>'

type类型表示bind,volume或者tmpfs

source指的是宿主机的目录

destination/dst/target表示文件或者目录挂载在容器中的路径

ro表示以只读方式挂载

操作

mount创建绑定卷
  • 创建绑定卷
bash 复制代码
mkdir -p /data/mydir/fd/webapp1
docker run -d -p 80:80 --name 容器名 --mount type=bind,source=/data/mydir/fd/webapp1,target=/usr/share/nginx/html nginx
  • 进入容器的终端,查看挂载点目录,和宿主机上查看,会发现都是没有文件,这也是存储卷和绑定卷最大的区别,绑定卷会将主机上的文件拷贝到容器中
bash 复制代码
docker exec -it 容器名 ls /usr/share/nginx/html
  • 在宿主机上添加index.html,通过浏览器访问,可以看到容器已经可以读取到宿主机的共享内容了
  • 删除容器,查看宿主机上的文件,发现还是存在,说明容器的删除不影响bind映射

tmpfs mount临时数据卷

映射于宿主机内存中,不存在于主机的可写层中,一旦容器停止运行,tmpfs mounts会被移除,数据就会丢失,用于高性能的临时数据存储。

但tmpfs不同于卷和绑定挂载,不能在容器之间共享tmpfs挂载,这个功能也只有在Linux上运行docker时才可用。

创建卷

--tmpfs

用于完成临时卷的映射。

bash 复制代码
--tmpfs /app
--mount

用于完成目录映射。

bash 复制代码
--mount '<key>=<value>,<key>=<value>'

type类型表示bind,volume或者tmpfs

destination/dst/target表示文件或者目录挂载在容器中的路径

tmpfs-size:tmpfs挂载的大小,默认无限制

tmpfs-mode:设置tmpfs权限模式,默认为1777,表示全局可读可写有粘滞位

操作

tmpfs参数创建临时卷
  • 创建临时卷启动容器
bash 复制代码
docker run --name 容器名 -d -p 80:80 --tmpfs /usr/share/nginx/html nginx
  • 进入容器可用看到nginx里的文件被覆盖了
bash 复制代码
docker exec -it 容器名 bash
#修改文件
#载入数据
docker reload 容器名
  • 添加一个index.html文件,修改文件内容

  • 停止容器,再启动容器,再次进入,可以看到tmpfs已经消失,说明内容是存在内存里面的

tmpfs失踪
  • 创建一个普通的容器,在容器里面写入一个文件load.txt,在宿主机上查找这个文件,文件是可以被找到的,因为此文件在容器的可写层
bash 复制代码
docker run --name 容器名 -d -p 80:80 nginx
docker exec -it 容器名 bash
mkdir -p /app
echo 1 > /app/mylabel.txt
exit
find / -name mylabel.txt
  • 创建一个临时卷,重复以上步骤,查找文件的时候发现文件是找不到的,因为tmpfs的内容不是存在容器的可写层中的
bash 复制代码
docker run --name 容器名 --tmpfs /app -d -p 80:80 nginx
docker exec -it 容器名 bash
echo 1 > /app/mylabel.txt
exit
find / -name mylabel.txt

MySQL恢复数据

  • 准备MySQL镜像
bash 复制代码
docker pull mysql:5.7
  • 创建容器
bash 复制代码
docker run --name mysql-demo -e MYSQL_ROOT_PASSWORD=密码 -itd -v /data/mydir/mysql-data:/var/lib/mysql mysql:5.7
  • 查看容器挂载信息
bash 复制代码
docker inspect 容器名 | grep "Mounts" -A 10
  • 连接MySQL的shell,创建数据库,输入密码
  • 在MySQL里床关键一个数据库,并且在这个数据库里创建一个表,在主机中查看volume,可以看到容器中MySQL创建的数据库和表数据以及持久化到宿主机挂载的目录下了
bash 复制代码
ls -l /data/mydir/mysql-data
  • 关闭服务器,删除MySQL容器,可以看到数据还在,再次启动容器,确认目录映射一致就可以恢复数据了
bash 复制代码
docker run --name mysql-demo-new -e MYSQL_ROOT_PASSWORD=密码 -d -v /data/mydir/mysql-data:/var/lib/mysql mysql5.7
  • 从MySQL客户端进去,查看其中的数据
bash 复制代码
docker exec -it mysql-demo-new bash
mysql -u root -p
相关推荐
F1FJJ3 小时前
只是想查个数据,不想装 phpMyAdmin
数据库·网络协议·容器·开源软件
.柒宇.4 小时前
基于 RHEL 9.7 搭建 Kubernetes v1.34 集群实战:Docker 运行时 (cri-dockerd) 与国内源配置详解
docker·云原生·容器·kubernetes·kubelet
F1FJJ4 小时前
Shield CLI:MySQL 插件 vs phpMyAdmin:轻量 Web 数据库管理工具对比
前端·网络·数据库·网络协议·mysql·容器
钟智强4 小时前
从2.7GB到481MB:我的Docker Compose优化实战,以及为什么不能全信AI
后端·docker
YMWM_5 小时前
docker在jetson thor的应用
运维·docker·容器·jetson thor
木子欢儿6 小时前
使用 Docker 快速搭建 MinIO 文件存储服务
运维·docker·容器
qq_297574677 小时前
K8s系列第十四篇:K8s 故障排查实战:常见故障定位与解决方法
java·docker·kubernetes
杭州杭州杭州8 小时前
Docker实验5
运维·docker·容器
pip install USART8 小时前
容器化场景常用kubectl命令
后端·容器·kubernetes