一、Docker数据卷出现得原因
Docker镜像是由一个各种层构成的只读模板,并且当镜像作为容器运行时,该容器会包含一个小型的数据只写层。造成:
- 数据被完全封闭在主机,会使运行中的应用程序在跨多个容器和应用程序共享数据产生困难。
- 数据在容器终止之后无法存留,并且难以将数据从容器中提取出来。
- 要向容器的写入层写入数据,需要一个存储驱动器来管理文件系统。存储驱动器无法提供好的读/写性能保障。像容器中写入大量数据将导致容器和Docker守护程序的内存不足。
二、解决方法
(1)tmpfs挂载
tmpfs会在tmpfs会在tmpfs中创建一个挂载,他是一个临时文件存储设施。tmpfs中挂载的目录会表现为一个挂载文件系统,但其实实在内存中存储的,而不是磁盘驱动器这样的持久化存储。
tmpfs挂载的使用范围被限定于Linux上的Docker容器。tmpfs挂载是临时的,其数据存储在Docker宿主机的内存中。一旦容器停止,tmpfs挂载也会被移除,而写入到tmpfs挂载的文件也会丢失。
创建tmpfs挂载:
docker run -it --name tmpfs-test --mount type=tmpfs,target=/tmpfs-mount ubuntu bash
docker run -it --name tmpfs-test --tmpfs /tmpfs-mount ubuntu bash
此状态下,容器的数据只会存放到宿主机的内存中,不会被写到宿主机的文件系统中,因此不能持久保存容器的应用数据。
适用场景:
- 当你出于安全原因,或者容器性能优化的原因(如需要写入大量的不持久的状态数据时),不需要容器的数据长久保存时可以使用这种方式。
(2)绑定挂载(Bind mounts方式下)
绑定挂载中,宿主机上的文件/目录会被挂载到容器中。该方式是适用于Linux宿主机。容器内的数据被存放到宿主机文件系统的任意位置,甚至存放到一些重要的系统目录或文件中。除了Docker之外的进程也可以任意对他们进行修改;
使用绑定挂载:
docker run -it --name mount-test --mount type=bind,source="$HOME",target=/host-name ubuntu bash
source : 为源,即被挂载的Docker宿主机目录。
target: 为挂载目标
docker run -it --nmae mount-test -v $HOME:/host-name ubuntu bash
运行结果:
Propagation:该属性表明了是否要将为绑定挂载所创建反射到绑定挂载的副本上去。
RW:该属性可以对挂载目录进行写入操作。
使用绑定挂载时,要注意,数据流时在Docker宿主机和容器之间双向流动。所以,如果所挂载的目录层级较高,就会造成一定的影响。为此,可以创建一个具有只读选项的绑定挂载。可以在docker run是给与一个只读参数。
docker run -it --name mount-test --mount type=bind,source="$HOME",target=/host-name,readonly ubuntu bash
docker run -it --nmae mount-test -v $HOME:/host-name:ro ubuntu bash
适用场景:
- 将宿主机的系统配置文件共享给容器,这是Docker为容器提供DNS配置的默认方式,即通过bind mounts的方式将宿主的的/etc/resolv.conf文件挂载到容器中。
- 将宿主机开发环境中的源代码或实验结果共享给容器。例如:你在宿主机上进行一个项目Maven的测试,每次你在宿主机上对Maven项目进行了更改后,容器就可以直接获取更改后的结果
- 当你可以确定宿主机的文件系统结构应该与容器内部完全一致时。
(3)卷
Docker卷是最推荐的将容器中存储的数据持久化的方法。卷完全由docker托管。相比于绑定挂载来说,卷有更多的优势:
- 卷比挂载更易于备份和转移
- 卷同时适用于Linux和Windows
- 可以顺利的跨多个容器共享卷
- 容器内的数据被存放到宿主机(linux)一个特定的目录下(/var/lib/docker/volumes/)。这个目录只有Docker可以管理,其他进程不能修改。
①、 创建卷
docker volume create --name=<name>
查看相关卷的具体信息
②、 精简卷
移除所有未使用的卷。未使用的卷会消耗相当多的磁盘空间。
③、移除卷
根据所提供的名称参数来删除卷。
④、在启动容器时使用卷
新建一个卷
docker run -it --name volume-test --mount target=/data-volume ubuntu bash
docker run -it --name volume-test -v:/data-volume ubuntu bash
新建卷的宿主机的位置如下图:
使用已经创建好的卷
docker run -it --name volume-test01 -d --mount source=nginx,target=/data-volume ubuntu bash
docker run -it --name volume-test01 -d -v:nginx:/data-volume ubuntu bash
适用场景:
- 多个容器间需要共享数据。如果volume没有手动被创建,它将会在首次挂载到某个容器之前被自动创建,当容器被停止或删除时,这个volume不会随之被删除。多个容器可以同时以rw或ro的方式挂载这个volume。只有手动指定删除volume,它才会被删除。
- 当宿主机并没有专用于Docker的文件系统结构时。使用volume可以使宿主机的配置与容器的运行解耦。
- 当你希望将数据保存到远程主机或云上。
- 当你希望在不同的宿主机直接备份/恢复/迁移数据时,volume是一个很好的选择。你可以停止运行使用volume的容器,然后直接备份volume所在的目录即可,如/var/lib/docker/volumes/<volume-name>
注:
卷的一项重要功能:当在容器文件系统中挂载卷时,卷将替换镜像在这一位置提供的内容。
三、另一种称呼
(1)指定路径挂载
[root@lab01 ~]# docker run -it -v /root/ceshi(宿主机地址):/root/ceshi(容器中需要被映射的地址) --name nginx01 nginx
这样挂载的结果就是宿主机地址和容器中的地址,无论是哪一方进行增加和删除操作,另一方均会同步。
当容器被停止后,在宿主机中的目录中添加或者删除文件时,容器再次开启后,均会被同步。
启动后可以根据以下命令 查看容器是否挂载成功
docker inspect 容器id
查看结果如下所示:
(2)匿名挂载
docker run -d -P --name tomcat01 -v /etc/tomcat(容器内地址) tomcat
此时只出现了乱码 数据卷
(3)具名挂载
[root@lab01 ~]# docker run -d -P --name tomcat02 -v juming:/etc/tomcat tomcat
d711f2a45b8fa8fcc4e78c8dd8ee775528a571c854de3fa71013905658baea1b
此处查看找到数据卷:
[root@lab01 ~]# docker volume ls
DRIVER VOLUME NAME
local 56fb2f38cba67314678c0072a65349a380e266dfa0efda1a7616c52f9ecfba2d
local d26b426d61e3f0addcd3c9f0a64e47e11660682aa5a3fc89554de064c6085061
local juming
此处查看可以找到映射到哪个地址:
四、如何区分指定路径挂载、匿名挂载、具名挂载
-v 宿主机路径:容器内路径 ----------> 指定路径挂载
-v 容器内路径 ---------->匿名挂载
-v 数据卷名称: 容器内路径 ---------->具名挂载
五、设置数据卷的读写权限
-v设置数据卷的读写权限
ro: read only 这个路径只可以宿主机来进行操作,容器内部无法进行操作
rw: read write
一旦设置了容器的读写权限,容器对我们挂载出来的东西就有了读写权限,且不可修改!
docker run -d -P --name tomcat02 -v juming:/etc/tomcat:ro tomcat
docker run -d -P --name tomcat02 -v juming:/etc/tomcat:rw tomcat
六、几个容器之间数据共享
命令:
[root@lab01 ~]# docker run -d -P --name nginx01 -v ceshi:/etc/nginx nginx
cc2865f1e092a610c56e5807a5ebf47871ad303c68560e0d4a71baed4500af2b
[root@lab01 ~]# docker run -d -P --name nginx02 --volumes-from nginx01 nginx
8d296f1bb1df624b6c9a7dda8b7930a277817abac6573242a440591b025b44b5
此时nginx01:
此时nginx02:
验证结果:
拓展:
此时如果有三个容器一一继承,在第一个容器删除后,另外两个还可以进行数据同步,因为在--volumes-from机制中,在进行数据卷设置时是进行复制。所以其他两个的数据同步不会被影响。
参考:
Docker的数据管理(volume/bind mount/tmpfs) - ExplorerMan - 博客园 (cnblogs.com)