Docker Volume 解密
@(容器技术)[Docker 数据卷, 帮助]
文章目录
什么是数据卷Volume
- Docker 镜像被存储在一系列的只读层。当我们开启一个容器时,Docker读取只读镜像并在顶部添加一个读写层,如果正在运行的容器修改了现有的文件,该文件将从底层的只读层拷贝到最顶部的读写层,在读写层中的旧版文件隐藏于该文件之下,并没有被破坏,仍然存在于镜像下。
当Docker 容器被删除,然后重新启动镜像时,将开启一个没有任何更改的新容器。这些更改会被丢失
。- 只读层以及顶部的读写层的组合被Docker称为
Union File System
联合文件系统
- 为了能够持久保存数据以及共享容器间的数据,Docker提出了Volume的概念:
volume是存在一个或多个容器中的特定文件或文件夹,这个目录能够独立于联合文件系统的形式在宿主机中存在,并为数据的共享与持久提供一下便利
。
数据卷Volume的特点
- volume在容器创建时就初始化,在容器运行时就可以使用其中的文件
- 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效方便
- 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作
- 对volume中数据操作不会影响到镜像本身,解耦了应用和数据
- volume的生存周期独立于容器的生存周期,即使删除容器,volume仍然会存在,没有任何容器使用的volume也不会被Docker删除
将Docker 数据挂载到容器
-
在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即数据不随着Container的生命周期结束而结束),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:
- 第一种[volume]:Docker管理宿主机文件系统的一部分,默认位于
/var/lib/docker/volumes
目录中,所有Container的数据都保存在了这个目录下边,由于没有在创建时指定卷,所以Docker帮我们默认创建许多匿名(就一堆很长ID的名字)卷 - 第二种[bind mounts]:意为着可以存储在宿主机系统的任意位置。bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。
- 第三种[tmpfs]:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统
- 第一种[volume]:Docker管理宿主机文件系统的一部分,默认位于
Volume的基本使用
管理卷
# 创建自定义卷
root@dengbiao:/home/dengbiao# docker volume create edc-nginx-vol
edc-nginx-vol
# 查看所有容器卷
root@dengbiao:/home/dengbiao# docker volume ls
DRIVER VOLUME NAME
local edc-nginx-vol
# 查看指定卷的详细信息
root@dengbiao:/home/dengbiao# docker inspect edc-nginx-vol
[
{
"CreatedAt": "2020-11-13T13:31:13+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data",
"Name": "edc-nginx-vol",
"Options": {},
"Scope": "local"
}
]
创建使用指定卷的容器
- 如果有了自定义容器卷,我们就可以创建使用这个容器卷的容器
- -v 代表挂载数据卷,这里使用容器卷
edc-nginx-vol
表示宿主机挂载点,/usr/share/nginx/html
是yum安装nginx的默认网页目录
- -v 代表挂载数据卷,这里使用容器卷
docker run -d -it --name=edc-nginx -p 8800:80 -v edc-nginx-vol:/usr/share/nginx/html nginx
- 从宿主机挂载点查看
root@dengbiao:/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data# pwd
/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data
root@dengbiao:/DATA/lib/docker-lib/volumes/edc-nginx-vol/_data# ls
50x.html index.html
- 在容器里边的改动,宿主机可以感知,反之宿主机里面的改动,容器里边同样可以感知到。
- 如果我们手动stop并且remove当前nginx容器,宿主机查看发现容器卷里面的文件还在,并没有被删除掉
清理卷
- 如果不再使用自定义数据卷了,那么可以手动清理掉
root@dengbiao:~# docker volume rm edc-nginx-vol
edc-nginx-vol
Bind Mounts 的基本使用
使用卷创建一个容器
- 将宿主机上的 /app/wwwroot 目录(如果没有会自动创建)挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)
root@dengbiao:~# docker run -d -it --name=edc-nginx -v /app/wwwroot:/usr/share/nginx/html nginx
c4ccddb7b472e08ac82fd80f6d2b6c7ee10611351039bea6539df1cbef2f3669
与volumes不同,bind mounts的方式会隐藏掉被挂载目录里面的内容(容器里面,如果非空的话),这里是/usr/share/nginx/html 目录下的内容被隐藏掉了,因此我们看不到
root@dengbiao:/app/wwwroot# ls
root@dengbiao:/app/wwwroot#
反之,我们可以将宿主机的文件随时挂载到容器中
# 宿主机创建index.html文件
root@dengbiao:/app/wwwroot# touch index.html
root@dengbiao:/app/wwwroot# vim index.html
# 进入容器查看
root@dengbiao:/app/wwwroot# docker exec -it edc-nginx /bin/bash
root@c4ccddb7b472:/# cd /usr/share/nginx/html
root@c4ccddb7b472:/usr/share/nginx/html# ls
index.html
验证绑定
root@dengbiao:/app/wwwroot# docker inspect edc-nginx
"HostConfig": {
"Binds": [
"/app/wwwroot:/usr/share/nginx/html"
],
清理
- 同volumes一样,当我们清理掉容器之后,挂载目录里面的文件仍然还在,不会随着容器的结束而消失,从而实现数据持久化
docker rm edc-nginx
匿名卷(匿名挂载)和命名卷(具名挂载)
什么是匿名卷?具名挂载?
- 匿名卷/匿名挂载:在进行数据卷挂载的时候
不指定宿主机的数据卷目录
,-v
命令后直接跟容器内数据卷路径
- 命名卷/具名挂载:在进行数据卷挂载的时候既指定
宿主机内数据卷所在路径
,又指定容器数据内卷所在路径
#匿名挂载(匿名卷)
docker run -d -p 6379:6379 --name mycentos -v /src/volume01
#具名挂载(命名卷) -v 宿主机数据卷所在路径:容器数据卷所在路径
docker run -d -p 6379:6379 --name mycentos -v /home/docker_volume:/src/volume01
- 也可以在在
dockerfile构建docker镜像的时候使用VOLUME保留字
来对数据卷进行挂载,此种挂载方式是匿名挂载
的,我们可以指定一个或多个数据卷,这样只要启动了该自定义容器镜像,则会自动进行数据挂载,不会出现忘记挂载导致数据不安全的情况
VOLUME ["容器内数据卷路径1","容器内数据卷路径2"……]
- 由于匿名卷挂载的时候只指定了
容器内数据卷路径
,至于该容器内数据卷的路径
到底和宿主机
中哪个目录进行数据挂载,可以通过docker inspect
命令查看
匿名卷和命名卷的区别
- 命名卷:在使用过一次后,以后挂载容器的时候还可以继续使用,一般需要保存数据的时候使用
命令卷
,宿主机中数据卷
的文件内容依然存在。 - 容器间可以实现数据共享
# 启动一个容器,并指定挂载及映射
docker run -it --name mycentos -v /home/centos_volume:/usr/local/volume01 centos:latest /bin/bash
# 进入容器中数据卷目录下创建文件,内容随意填写
cd /usr/local/volume01
vim file.txt
# 查看宿主机的数据卷路径下是否有创建的文件
dengbiao@dengbiao:~$ cd /home/centos_volume/
dengbiao@dengbiao:/home/centos_volume$ ll
总用量 12
drwxr-xr-x 2 root root 4096 11月 13 14:45 ./
drwxr-xr-x 4 root root 4096 11月 13 14:44 ../
-rw-r--r-- 1 root root 17 11月 13 14:45 file.txt
# 退出删除容器
docker rm mycentos
# 再启动新容器
docker run -it --name mycentos -v /home/centos_volume:/usr/local/volume01 centos:latest /bin/bash
# 再次进入容器,查看容器中数据卷路径是否有被创建的文件
cd /usr/local/volume01/
ls
file.txt
- 匿名卷:每次创建新的容器,Docker都会随机自动创建
宿主机内的数据卷路径
(那一大长串ID),不同的容器,宿主机内的数据卷路径均不相同
。匿名卷一般用来存储无关痛痒的数据 - 容器间不可以实现数据共享
# 启动一个容器,并指定挂载及映射
docker run -it --name mycentos -v /usr/local/volume01 centos:latest /bin/bash
# 进入容器中数据卷目录下创建文件,内容随意填写
cd /usr/local/volume01/
vi file.tx
# inspect 查看宿主机的数据卷路径
docker inspect mycentos
"Mounts": [
{
"Type": "volume",
"Name": "2c90ceeb2597fdba5391e646e5a79d8f5c9dba816ace6fc34e30803a990377fe",
"Source": "/DATA/lib/docker-lib/volumes/2c90ceeb2597fdba5391e646e5a79d8f5c9dba816ace6fc34e30803a990377fe/_data",
"Destination": "/usr/local/volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
# 查看宿主机的数据卷路径下是否有创建的文件
ls /DATA/lib/docker-lib/volumes/2c90ceeb2597fdba5391e646e5a79d8f5c9dba816ace6fc34e30803a990377fe/_data
file.txt
# 退出删除容器
exit
docker rm mycentos
# 再启动新容器
docker run -it --name mycentos -v /usr/local/volume01 centos:latest /bin/bash
# insepect 查看宿主机的数据卷路径
docker inspect mycentos
"Mounts": [
{
"Type": "volume",
"Name": "e68db612cfe89440dfee3f4de14b47ba72b6617729c3da68ecce4f75eb336cb2",
"Source": "/DATA/lib/docker-lib/volumes/e68db612cfe89440dfee3f4de14b47ba72b6617729c3da68ecce4f75eb336cb2/_data",
"Destination": "/usr/local/volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
# 观察两次容器的inspect信息:`宿主机内的数据卷路径`
Source 字段 均不相同
# 再次进入容器,查看容器中数据卷路径是否有被创建的文件
cd /usr/local/volume01/
无内容