Docker Volume存储卷的实现
作者:诡异森林。
什么是存储卷?
Docker的存储卷是一种将宿主机的本地文件系统中的某个目录与容器内部的文件系统中的某个目录建立绑定关系的机制。这种绑定关系意味着,当在容器的这个目录下写入数据时,会同步到宿主机的这个目录中;同样,在宿主机的这个目录下写入数据也会同步到容器的这个目录下。
存储卷的作用
- 数据持久化:存储卷使得数据可以独立于容器的生命周期存在。即使容器被删除,只要存储卷不被删除,数据就不会丢失。
- 数据共享:多个容器可以共享同一个存储卷,从而实现数据共享。
- 提高数据访问效率:通过存储卷,容器可以直接访问宿主机上的数据,避免了通过镜像层访问数据的低效率问题。
存储卷的类型
- Bind mount volume(绑定挂载卷):指向主机文件系统上用户指定位置的卷。使用
-v
或--volume
命令时,需要指定宿主机上卷的名称或完整路径,以及容器内的挂载点。如果指定的卷不存在,Docker会自动创建它。 - Docker-managed volume(Docker管理卷):由Docker守护进程在主机文件系统的一部分中创建的托管卷。使用
docker volume create
命令可以创建一个新的Docker管理卷。这些卷存储在主机文件夹中(在Linux系统中,通常位于/var/lib/docker/volumes/
路径下),并由Docker进行管理。 - tmpfs mount (临时数据卷):映射到于宿主机内存中,一旦容器停止运行,
tmpfs mounts
会被移除,数据就会丢失,用于高性能的临时数据存储。
命令操作
创建卷 docker create volume
docker volume create [OPTIONS] [VOLUME]
创建一个存储卷;
参数:
- -d, --driver:指定驱动,默认是 local
- –label:指定元数据
例如:
root@VM-8-12-ubuntu:~#docker volume create my-vol my-vol
docker volume inspect
查看卷的详细信息
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
参数:
- -f:指定相应个格式,如 json
例如:
docker volume ls
列出存储卷的列表
docker volume ls [OPTIONS]
参数:
- –format:指定相应个格式,如 json,table
- –filter,-f: 过滤
- -q: 仅显示名称
例如
docker volume rm
删除存储卷,需要让容器不使用对应卷才可以删除
docker volume rm [OPTIONS] VOLUME [VOLUME...]
参数:
- -f,–force:强制删除
docker volume prune
删除不使用的卷
docker volume prune [OPTIONS]
参数:
- -f,–force:强制删除
- –filter:过滤
通过 docker run 命令 选项 -v 进行创建卷
docker run -v name:directory[:options]
第一个参数:卷名称
第二个参数:卷映射到容器的目录
第三个参数:选项,如 ro 表示 readonly
例如:
docker run -d --name devtest -v myvol2:/app nginx:1.23.4
通过命令查看:
docker container inspect devtest
通过 docker run 命令 选项–mount进行创建卷
目的:完成目录映射
--mount '<key>=<value>,<key>=<value>'
参数:
- type : 类型表示 bind, volume, or tmpfs
- source ,src :对于命名卷,这是卷的名称。对于匿名卷,省略此字段。
- destination,dst,target:文件或目录挂载在容器中的路径
- ro,readonly: 只读方式挂载
例如:
docker run -d --name devtest2 --mount source=myvol2,target=/app nginx:1.23.4
通过命令查看:
docker container inspect devtest2
操作实例:docker -v 创建管理卷
创建一个nginx容器,映射端口8080,创建管理卷为test_volume :
docker run --name mynginx1 -d -p 8080:80 -v test_volume:/usr/share/nginx/html:ro nginx:1.23.4
查看对应信息:
docker inspect test_volume
进入挂载点的对应目录里
cd /data/var/lib/docker/volumes/test_volume/_data
修改对应的内容:
echo "Test Volume " > index.html
浏览器查看:
进入到容器中,并且进入到对应的html目录下
docker exec -it mynginx1 bash cd /usr/share/nginx/html
无法对其进行删除指定 ro 的话宿主机可以修改,但是容器里面无法修改
卷的生命周期:如果卷没有被删除,那么不管容器怎么样,卷仍然存在;只有卷被删除了,那么卷的生命周期才会结束.
如果两个容器指定同一个卷,那么卷可以被共享;
利用docker run 参数-v创建绑定卷
docker run -v name:directory[:options] .........
第一个参数:宿主机目录,这个和管理卷是不一样的
第二个参数:卷映射到容器的目录
第三个参数:选项,如 ro 表示 readonly
例如:
docker run -d -it --name mynginx2 -v "$(pwd)"/target:/app nginx:latest
如果 target 目录不存在,启动不会报错,这是-v 和–mount 方式的区别
这样 当前目录下target目录就与容器的app目录绑定好了。
利用docker run 参数 --mount 参数创建绑定卷
--mount '<key>=<value>,<key>=<value>'
参数:
- type : 类型表示 bind, volume, or tmpfs
- source ,src :宿主机目录,这个和管理卷是不一样的。
- destination,dst,target:文件或目录挂载在容器中的路径
- ro,readonly: 只读方式挂载
例如:
创建一个容器,端口映射为8081,将宿主机的webapp1/挂载到容器指定目录中
docker run -d -p 8081:80 --name mynginx4 --mount type=bind,source=/data/ahri/webapp1,target=/usr/share/nginx/html nginx:1.23.4
如果 webapp1 目录不存在会启动报错
查看容器的详细内容,可以看到对应的挂载信息:
docker inspect mynginx4
查看容器的html目录下的内容,发现为空:
docker exec -it mynginx4 ls /usr/share/nginx/html
这是 bind mount 模式和 volume 模式最大的不同点
进入宿主机的webapp1目录中,向index.html目录写入内容:
cd webapp1 echo "Test Bind Volume" >>index.html
通过浏览器可以看到相对应的内容:
操作实例 绑定卷的共享
再次创建一个容器绑定相同的卷:
docker run -d --name mynginx5 -p 8082:80 -v /data/ahri/webapp1:/usr/share/nginx/html nginx:1.23.4
curl 127.0.0.1:8081 curl 127.0.0.1:8082
可以看到内容相同;
改变文件内容,结果随之改变:
echo "bind mount after edit" > index.html
临时卷 tmpfs 的创建 -v
不同于其他卷,tmpfs临时卷无法共享;且这个功能只能在Linux上使用.
创建一个容器,并且有一个临时卷挂载在html目录下:
docker container run --name tmpfs1 -d -p 8080:80 --tmpfs /usr/share/nginx/html nginx:1.23.4
进入到容器中的html目录下,并查看目录下的内容,发现tmpfs 也会覆盖容器里面的文件:
docker exec -it tmpfs1 bash cd /usr/share/nginx/html ls -l
向index.html写入内容,并通过浏览器查看:
echo "Hello World from tmpfs" > index.html
退出容器并停止运行,再次启动容器并进入到html目录下,发现目录为空,也就是说内容是存在内存里面的:
exit docker stop tmpfs1 docker start tmpfs1 docker exec -it tmpfs1 bash ls /usr/share/nginx/html/
临时卷 tmpfs 的创建 --mount
不同于其他卷,tmpfs临时卷无法共享;且这个功能只能在Linux上使用.
docker run --name tmpfs1 -d -p 8080:80 --mount type=tmpfs,destination=/usr/share/nginx/thml,tmpfs-size=1m nginx:1.23.4
–mount还能指定参数来限制内存的大小.
实例 tmpfs失踪
创建一个容器,并进入:
docker run -d -it --name tmptest nginx:1.23.4 docker exec -it tmptest bash
创建一个app目录向该目录创建一个新文件mylabel.txt ,然后在宿主机查看:
mkdir -p /app echo 1 > /app/mylabel.txt exit find / -name mylabel.txt
可以看到,文件被找到了,是因为他在容器的可写层.
创建一个有临时卷的容器,挂载点是/app,然后进入到容器中:
docker run -d --name tmptest2 --tmpfs /app nginx:1.23.4 docker exec -it tmptest2 bash
向该目录写入新文件,退出到宿主机,并查看,发现查看不到对应文件,所以 tmpfs 的内容不是存储在我们的容器的可写层里面的。
echo 222 > /app/mynewlabel.txt exit find / -name mynewlabel.txt
实例 mysql的灾难性恢复
创建一个mysql容器,并且将宿主机的mysql-data挂载到容器中,设置初始密码123456
docker run --name mysql-demo -e MYSQL_ROOT_PASSWORD=123456 -it -d -v /data/ahri/mysql-data:/var/lib/mysql mysql:5.7
查看容器的挂载详情:
docker container inspect mysql-demo | grep "Mounts" -A 10
进入容器并启动MySQL客户端:
docker exec -it mysql-demo /bin/bash mysql -u root -p
创建一个数据库:
create database user;
创建一个表并写入数据:
use user; create table student(sno char(3),sname varchar(10)); insert into student values('1','zs'),('2','ls');
退出容器,并查看mysql-data挂载的内容:
exit
停止容器的运行并删除:
docker stop mysql-demo docker rm mysql-demo
虽然容器被删除了,但数据仍然保存在mysql-data目录下.
我们重新启动容器
docker run --name mysql-demo-new -e MYSQL_ROOT_PASSWORD=123456 -it -d -v /data/ahri/mysql-data:/var/lib/mysql mysql:5.7
docker exec -it mysql-demo-new bash mysql -u root -p
进入到user数据库中,并查看列表:
use user;
常见问题:什么时候用 Volume,什么时候用 bind、tmpfs?
Volume
**Volume是Docker管理的一个存储卷,独立于容器的生命周期。**当容器被删除时,Volume中的数据不会丢失,除非显式地删除Volume。
适用场景:
- 数据持久化:需要确保数据在容器删除或重新创建后仍然可用。
- 数据共享:多个容器之间需要共享数据。
- 数据管理:利用Docker的Volume管理功能,可以更方便地进行数据的备份、恢复和迁移。
Bind mounts
Bind mounts是将宿主机上的文件或目录直接挂载到容器中,实现数据的共享和访问。这种方式的数据由宿主机管理,而不是Docker。
适用场景:
- 灵活的数据挂载:需要指定宿主机上的任意文件或目录作为挂载目标。
- 现有数据的集成:容器需要访问宿主机上已经存在的数据,例如配置文件、日志文件等。
- 性能要求:在某些情况下,Bind mounts可能比Volume具有更好的性能,因为它们直接访问宿主机的文件系统。
Tmpfs
Tmpfs是一种特殊的挂载方式,它将数据存储在宿主机的内存中,而不是持久化存储。当容器停止时,Tmpfs中的数据将被删除。
适用场景:
- 临时存储:需要临时存储数据,例如在处理请求时生成的中间结果。
- 提高性能:需要频繁读写临时数据的场景,因为Tmpfs的数据存储在内存中,读写速度更快。
- 安全性:不希望数据在容器停止后仍然保留在宿主机上。
到此这篇关于Docker Volume存储卷的实现的文章就介绍到这了,更多相关Docker Volume存储卷内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!