一、什么是docker数据卷:
我们都知道在docker中,容器的数据读写默认发生在容器的存储层,当容器被删除时其上的数据将会丢失,如果想实现数据的持久化,就需要将容器和宿主机建立联系(将数据从宿主机挂载到容器中),通俗的讲,数据卷就是在容器和宿主机之间实现的数据共享。
二、docker支持的三种数据挂载方式:
docker提供了三种不同的方式将数据从宿主机挂载到容器中:
1. volume:Docker管理宿主机文件系统的一部分,默认位于/var/lib/docker/volumes 目录中,(这是最常用的方式)
由上图可以知道,目前所有的Container的数据都保存在这个目录下面,由于没有在创建前指定卷,所以docker帮我们默认创建许多匿名(就上面这一堆很长ID的名字)卷。
2. bind mounts:可以存储在宿主机的任何位置(比较常用的方式)
但是,bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也可能不一样,这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。
3. tmpfs nounts:挂载存储在宿主机的内存中,不会写入宿主机的文件系统(一般都不会用的方式)
三种存储方式适用场景:
volumes:
- 多个运行容器间共享数据
- 当Docker主机不确保具有给定的目录或文件
- 备份、恢复、或将数据从一个Docker主机迁移到另一个Docker主机时
bind mount:
- 主机与容器共享配置文件(Docker默认情况下通过这种方式为容器提供DNS解析,通过将/etc/resolv.conf挂载到容器中)
- 共享源代码或build artifacts(比如将Maven的target/目录挂载到容器中,每次在Docker主机中build Maven工程时,容器能够访问到那些rebuilt artifacts)
- 当 docker主机中的文件或目录结构和容器需要的一致时
tmpfs mount:
- 既不想将数据存于主机,又不想存于容器中时(这可以是出于安全的考虑,或当应用需要写大量非持久性的状态数据时为了保护容器的性能)。
三种方式官方示意图:
三、volume的基本使用
3.1管理卷
docker volume create nginx-vol // 创建一个自定义容器卷名为“nginx-vol” docker volume ls // 查看所有容器卷 docker volume inspect nginx-vol // 查看指定容器卷“nginx-vol”详情信息
例如:创建一个名为“nginx-vol”的自定义容器卷:
[root@node1 ~]# docker volume create nginx-vol
nginx-vol
[root@node1 ~]# docker volume inspect nginx-vol
[
{
"CreatedAt": "2021-07-20T12:03:14+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/nginx-vol/_data",
"Name": "nginx-vol",
"Options": {},
"Scope": "local"
}
]
重要字段解释:
- CreatedAt:创建时间
- Mountpoint:挂载点
- Name:数据卷名称
3.2创建使用指定卷的容器
创建了自定义的容器卷,我们可以创建一个使用这个数据卷的容器,我们以nginx为例:
docker run -d -it --name=gxw -p 8080:80 -v nginx-vol:/root/ nginx
字段解释:
- -v:代表的是挂载数据卷,这里我们使用的是自定义的数据卷nginx-vol,并且将数据卷挂载到容器的/root/目录下
- 如果没有通过-v指定,那么Docker会默认帮我们创建匿名的数据卷进行映射和挂载
创建好容器之后,我们可以进入容器里面去看看:
[root@k8s-node1 ~]# docker exec -it gxw bash
root@1b6dd7ee08c7:/# cd /root/
root@1b6dd7ee08c7:~# ls
里面此时没有任何文件存在,这时,我们试着mkdir一个空目录进去测试一下:
root@1b6dd7ee08c7:~# mkdir aaa
root@1b6dd7ee08c7:~# ls
aaa
可以看到我们创建的目录,这时我们启动一个新的终端,进入刚刚创建的容器卷中进行查看:
[root@k8s-node1 ~]# cd /var/lib/docker/volumes/nginx-vol/_data
[root@k8s-node1 _data]# ls
aaa
可以看到,我们访问的目录下面也有同样的一个目录,由此可见,volume帮我们做的类似于一个软连接的功能,在容器里面的改动,我们可以在宿主机中感知,而在宿主机里面的改动,在容器中也是可以感知的。
我们可以使用 docker inspect 查看容器的情况:后面+容器ID
[root@node1 ~]# docker inspect 1b6dd7ee08c7
"Mounts": [
{
"Type": "volume",
"Name": "nginx-vol",
"Source": "/var/lib/docker/volumes/nginx-vol/_data",
"Destination": "/root",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
注意看此段落:
这时,如果我们手动stop或者remove当前nginx容器,我们会发现容器卷里面的文件还在,并没有被删掉:
[root@node1 ~]# docker stop gxw
gxw
[root@node1 ~]# docker rm gxw
gxw
[root@node1 ~]# cd /var/lib/docker/volumes/nginx-vol/_data
[root@node1 _data]# ls
aaa
由此可以验证,在数据卷里面的东西是可以持久化的,如果下次还需要创建nginx容器,那么还是可以复用当前数据卷里面的文件的。
此外,我们还可以启动多个nginx容器实例,并且共享同一个数据卷,复用性和扩展性很强。
3.3:清理卷
如果不再使用自定义卷了,那么是可以手动清理掉的:
docker stop gxw // 暂停容器实例
docker rm gxw // 移除容器实例
docker volume rm nginx-vol // 删除自定义数据卷