目录
[3. 只读挂载](#3. 只读挂载)
[2.Bind mount](#2.Bind mount)
[Bind mounts使用场景](#Bind mounts使用场景)
[3.tmpfs mounts使用场景](#3.tmpfs mounts使用场景)
[4.Bind mounts和Volumes行为上的差异](#4.Bind mounts和Volumes行为上的差异)
[5.docker file将存储内置到镜像中](#5.docker file将存储内置到镜像中)
docker四种方式:默认、volumes数据卷、bind mounts挂载、tmpfs mount(仅在linux环境中提供),其中volumes、bind mounts两种实现持久化容器数据;
-
默认:数据保存在运行的容器中,容器删除后,数据也随之删除
-
volumes:数据卷,数据存放在主机文件系统/var/lib/docker/volumes/目录下,该目录由docker管理,其他进行不允许修改,推荐该种方式持久化数据
-
binf mounts:直接挂载主机文件系统的任何目录或文件,类似主机和容器的共享目录,主机上任何进行都可以访问修改,容器种也可以修改,这种方式操作较方便
-
tmpfs:数据暂存在主机内存中,不会写入文件系统,重启后,数据删除。
1.Volumes
1.Volumes使用场景
-
在多个容器间共享数据。
-
无法确保Docker主机一定拥有某个指定的文件夹或目录结构,使用Volumes可以屏蔽这些宿主机差异。
-
当你希望将数据存储在远程主机或云提供商上。
-
当你希望备份,恢复或者迁移数据从一台Docker主机到另一台Docker主机,Volumes是更好的选择。
2.持久将资源存放
bash
[root@localhost ~]# docker run -itd --name web02 -v /usr/share/nginx/html -p 80:80 nginx
47cc88c32968adfecd0040232e37ad3e7fca59d1b32715473c8975a115a5cd71
[root@localhost ~]# docker inspect -f '{{.Mounts}}' web02
[{volume 0f0c1c10037c7519b5015b34e377a9a5bb211a98455745d29060e9b0ef464f83 /var/lib/docker/volumes/0f0c1c10037c7519b5015b34e377a9a5bb211a98455745d29060e9b0ef464f83/_data /usr/share/nginx/html local true }]
[root@localhost ~]# cd /var/lib/docker/volumes/0f0c1c10037c7519b5015b34e377a9a5bb211a98455745d29060e9b0ef464f83/_data
[root@localhost _data]# ls
50x.html index.html
当从外部修改时,内部也会更改
bash
[root@localhost _data]# echo "test successful" > index.html
3. 只读挂载
在容器内,无法对挂载目录来进行写入
bash
[root@localhost _data]# docker run -itd --name web05 -v /nginx/html/:/usr/share/nginx/html:ro -p 80:80 nginx
420c9344b0bb31c885f514a4a98c9761a0e3a636b50420eadc1ce7e10c6c2a2d
[root@localhost _data]# docker exec -it web05 /bin/bash
root@420c9344b0bb:/# cd /usr/share/nginx/html/
root@420c9344b0bb:/usr/share/nginx/html# touch 1.txt
touch: cannot touch '1.txt': Read-only file system
2.Bind mount
Bind mounts使用场景
-
在宿主机和容器间共享配置文件。例如将nginx容器的配置文件保存在宿主机上,通过Bind mounts挂载后就不用进入容器来修改nginx的配置了。
-
在宿主机和容器间共享代码或者build输出。例如将宿主机某个项目的target目录挂载到容器中,这样在宿主机上Maven build出一个最新的产品,可以直接咋i容器中运行,而不用生成一个新的镜像。
-
Docker主机上的文件或目录结构是确定的
创建一个nginx将前端文件映射到容器
bash
[root@localhost ~]# mkdir -p /nginx/html
[root@localhost ~]# cd /nginx/html/
[root@localhost html]# echo "hello world" > index.html
[root@localhost ~]# docker run --name web01 -itd -p 80:80 -v /nginx/html/:/usr/share/nginx/html/ nginx
f8c5174eb4e7d960e9c9a39121a7eeef7837b0936919ce5461d1526b9879ea43
3.tmpfs mounts使用场景
- 当你因为安全或其他原因,不希望将数据持久化到容器或宿主机上,那你可以使用tmpfs mounts模式。
4.Bind mounts和Volumes行为上的差异
-
如果你将一个空Volume挂载到一个非空容器目录上,那么这个容器目录中的文件会被复制到Volume中,即容器目录原有文件不会被Volume覆盖。
-
如果你使用Bind mounts将一个宿主机目录挂载到容器目录上,此容器目录中原有的文件会被隐藏,从而只能读取到宿主机目录下的文件
属性 | bind mount | docker managed volume |
---|---|---|
volume | 可任意指定 | /var/lib/docker/volumes固定指定位置 |
对已有mount point影响 | 隐藏并替换为volume | 原有数据复制到volume |
是否支持单个文件 | 支持 | 不支持,只支持目录 |
权限控制 | 可以设置为只读,默认为读写权限 | 无控制,均为读写权限 |
移植性 | 移植性弱,与host path绑定 | 移植性强,无需指定host目录 |
5.docker file将存储内置到镜像中
bash
vi Dockerfile
FROM nginx:latest
VOLUME /usr/share/nginx/html
构建
bash
[root@localhost ~]# [root@localhost ~]# docker build -t voltest .
[root@localhost ~]# docker run -itd --name voltest1 voltest
1c76e5439f2a0f922841850ba76d50156c2aae5ab3d3c8327c1158510b0eded8
查看存储
bash
[root@localhost ~]# docker inspect -f '{{.Mounts}}' 1c76e543
[{volume 22019515c7c4c7f0798d360a8e3e281c391fdbe0bfd343a8b9ae8a2138969265 /var/lib/docker/volumes/22019515c7c4c7f0798d360a8e3e281c391fdbe0bfd343a8b9ae8a2138969265/_data /usr/share/nginx/html local true }]
6.volumes管理
众所周知,当容器被删除后,关联的存储卷,将不会被删除,如何来管理他们呢
1.查看存储卷
bash
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local 0f0c1c10037c7519b5015b34e377a9a5bb211a98455745d29060e9b0ef464f83
local 22019515c7c4c7f0798d360a8e3e281c391fdbe0bfd343a8b9ae8a2138969265
2.删除存储卷
当容器被删除后,存储卷将会与其他容器没有任何关联,也被称作孤儿volume
bash
[root@localhost ~]# docker volume rm 0f0c1c10037c7519b5015b34e377a9a5bb211a98455745d29060e9b0ef464f83
0f0c1c10037c7519b5015b34e377a9a5bb211a98455745d29060e9b0ef464f83
删除容器不存在的所有卷
bash
[root@localhost ~]# docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
3.查看存储卷的详细信息
bash
[root@localhost ~]# docker volume inspect 127bbbfc3a93d16920da4003eaa590f939426bcb60085801c8c9187bb8651359
[
{
"CreatedAt": "2023-07-12T18:04:58+08:00",
"Driver": "local",
"Labels": {
"com.docker.volume.anonymous": ""
},
"Mountpoint": "/var/lib/docker/volumes/127bbbfc3a93d16920da4003eaa590f939426bcb60085801c8c9187bb8651359/_data",
"Name": "127bbbfc3a93d16920da4003eaa590f939426bcb60085801c8c9187bb8651359",
"Options": null,
"Scope": "local"
}
]
7.Volumes操作管理
1.Volume管理
创建一个Volume:
bash
$ docker volume create my-vol
查看Volumes:
bash
$ docker volume ls
local my-vol
$ docker volume inspect my-vol
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
我么可以看到创建的 Volume my-vol 保存在目录**/var/lib/docker/volumes/**
下,以后所有针对该 Volume 的写数据都会保存中目录**/var/lib/docker/volumes/my-vol/_data**
下。
删除一个 Volume:
bash
$ docker volume rm my-vol
或者删除所有未使用的 Volumes:
bash
docker volume prune
2.挂载数据卷到容器目录
创建了一个 Volume 之后,我们可以在运行容器时通过指定 -v 或 --mount 参数来使用该 Volume:
使用--mount
参数:
bash
$ docker run -d \
--name=nginxtest \
--mount source=nginx-vol,destination=/usr/share/nginx/html \
nginx:latest
source 指定 volume,destination 指定容器内的文件或文件夹。
或者使用 -v 参数:
bash
$ docker run -d \
--name=nginxtest \
-v nginx-vol:/usr/share/nginx/html \
nginx:latest
挂载成功后,容器从 /usr/share/nginx/html 目录下读取或写入数据,实际上都是从宿主机的 nginx-vol 数据卷中读取或写入数据。因此 Volumes 或 Bind mounts 也可以看作是容器和宿主机共享文件的一种方式。
-v 参数使用冒号分割 source 和 destination,冒号前半部分是 source,后半部分是 destination。
如果你挂载一个还不存在的数据卷,Docker 会自动创建它。(因此创建数据卷那一步非必需)
如果容器中的待挂载的目录不是一个空目录,那么该目录下的文件会被复制到数据卷中。(Bind mounts下,宿主机上的目录总会覆盖容器中的待挂载目录)
-v 参数和 --mount 参数总的来说功能几乎相同,唯一的区别是在运行一个 service 时只能够 --mount 参数来挂载数据卷。
3.使用只读数据卷
有些情况下,我们希望某个数据卷对某个容器来说是只读的,可以通过添加 readonly 选项来实现:
bash
$ docker run -d \
--name=nginxtest \
--mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
nginx:latest