卷的本质是文件或者目录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上(直接挂载主机上的文件或目录到容器中)。卷的概念不仅解决了数据持久化的问题,还解决了容器间共享数据的问题。使用卷可以将容器内的目录或文件持久化,当容器重启后保证数据不丢失,例如我们可以使用卷将 MySQL 的目录持久化,实现容器重启数据库数据不丢失。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
卷的用途就是将Docker内的数据保存到宿主机的磁盘中
在启动容器的时候添加-v参数即可, 使用格式为:-v HOST_PATH:CONTIANAER_PATH
完整命令:
docker run -v 宿主机路径:容器内路径[:读写权限] --privileged=true [其它参数] image
- 读写权限 是对容器内的限制,默认为rw 可读可写,其它可选值还有ro 只读
- –privileged=true,设置为true, container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限,建议加上,否则可能会出现:“ cannot open directory .: Permission denied”
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,ESELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用-privleged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即**使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。
挂载后,
1 docker修改挂载文件、目录,主机同步获得
2 主机修改挂载文件、目录,docker同步获得
3 docker容器stdp,主机修改,docker容器重启数据自动同步。
docker inspect c72#(容器ID)
#查看输出的Mounts 部分 Source 宿主机路径,Destination 容器内路径
"Mounts": [
{
"Type": "bind",
"Source": "/tmp/dockerubuntu",
"Destination": "/tmp/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
docker run -v 宿主机路径:容器内路径[:读写权限] --privileged=true [其它参数] image
启动时加参数
–volumes-from 父类容器ID
其实质就是: -v 父类容器ID的挂载规则 ,容器移动后 跟父容器除挂载目录一样外并无其它关系
我们使用以下命令创建一个名为 myvolume 的数据卷:
$ docker volume create myvolume
除了使用docker volume create的方式创建卷,我们还可以在 Docker 启动时使用 -v 的方式指定容器内需要被持久化的路径,Docker 会自动为我们创建卷,并且绑定到容器中,使用命令如下:
Docker 卷的目录默认在 /var/lib/docker/volumes 下
$ docker run -d --name=nginx-volume -v /usr/share/nginx/html nginx
$ docker volume ls
DRIVER VOLUME NAME
local bcc2091bf5cd5247c1b28ac287450a086d6eee9632d9d1b9f69171
可以看到,Docker 自动为我们创建了一个名称为随机 ID 的卷。
已经创建的数据卷可以使用 docker volume ls 命令查看。
$ docker volume ls
DRIVER VOLUME NAME
local myvolume
通过输出可以看到 myvolume 卷已经创建成功。
如果想要查看某个数据卷的详细信息,可以使用docker volume inspect命令。例如,我想查看 myvolume 的详细信息,命令如下:
$ docker volume inspect myvolume
[
{
"CreatedAt": "2020-09-08T09:10:50Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/myvolume/_data",
"Name": "myvolume",
"Options": {},
"Scope": "local"
}
]
通过docker volume inspect命令可以看到卷的创建日期、命令、挂载路径信息。
使用docker volume创建的卷在容器启动时,添加 --mount 参数指定卷的名称即可使用。
这里我们使用上一步创建的卷来启动一个 nginx 容器,并将 /usr/share/nginx/html 目录与卷关联,命令如下:
$ docker run -d --name=nginx --mount source=myvolume,target=/usr/share/nginx/html nginx
这样 主机的 /var/lib/docker/volumes/myvolume/_data 目录 就和容器内的/usr/share/nginx/html 目录 挂载上了,之后,两者内的文件实现了数据共享
在我们创建 Docker 卷时,Docker 会把卷的数据全部放在 /var/lib/docker/volumes/卷名/_data目录下,并把此目录绑定到容器中。因此我们在容器中挂载卷的目录下操作文件,实际上是在操作主机上的 _data 目录
容器的删除并不会自动删除已经创建的数据卷,因此不再使用的数据卷需要我们手动删除,删除的命令为 docker volume rm 。例如,我们想要删除上面创建 myvolume 数据卷,可以使用以下命令:
$ docker volume rm myvolume
这里需要注意,正在被使用中的数据卷无法删除,如果你想要删除正在使用中的数据卷,需要先删除所有关联的容器。
有时候,两个容器之间会有共享数据的需求,很典型的一个场景就是容器内产生的日志需要一个专门的日志采集程序去采集日志内容,例如我需要使用 Filebeat (一种日志采集工具)采集 nginx 容器内的日志,我就需要使用卷来共享一个日志目录,从而使得 Filebeat 和 nginx 容器都可以访问到这个目录,这时就需要用到容器之间共享数据卷的方式。
那如何实现容器与容器之间数据共享呢?下面我举例说明。
首先使用docker volume create命令创建一个共享日志的数据卷。
$ docker volume create log-vol
启动一个生产日志的容器(下面用 producer 窗口来表示):
$ docker run --mount source=log-vol,target=/tmp/log --name=log-producer -it busybox
然后新打开一个命令行窗口,启动一个消费者容器(下面用 consumer 窗口来表示):
docker run -it --name consumer --volumes-from log-producer busybox
使用volumes-from参数可以在启动新的容器时来挂载已经存在的容器的卷,volumes-from参数后面跟已经启动的容器名称或ID。
下面我们切换到 producer 窗口,使用以下命令创建一个 mylog.log 文件并写入 “Hello,My log.” 的内容:
/ # cat </tmp/log/mylog.log
Hello, My log.
EOF```
然后我们切换到 consumer 窗口,查看一下相关内容:
```bash
/ # cat /tmp/log/mylog.log
Hello, My log.
可以看到我们从 producer 容器写入的文件内容会自动出现在 consumer 容器中,证明我们成功实现了两个容器间的数据共享。
总结一下,我们首先使用 docker volume create 命令创建了 log-vol 卷来作为共享目录,log-producer 容器向该卷写入数据,consumer 容器从该卷读取数据。这就像主机上的两个进程,一个向主机目录写数据,一个从主机目录读数据,利用主机的目录,实现了容器之间的数据共享。
要实现主机与容器之间数据共享,更简单更常用的办事只需要我们在启动容器的时候添加-v参数即可,
使用格式为:-v HOST_PATH:CONTIANAER_PATH