1.什么是容器数据卷
docker的镜像是由多个只读的文件系统叠加在一起形成的。当我们在我启动一个容器的时候,docker会加载这些只读层并在这些只读层的上面(栈顶)增加一个读写层。这时如果修改正在运行的容器中已有的文件,那么这个文件将会从只读层复制到读写层。该文件的只读版本还在,只是被上面读写层的该文件的副本隐藏。当删除docker,或者重新启动时,之前的更改将会消失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。
为了很好的实现数据保存和数据共享,Docker提出了Volume这个概念,简单的说就是绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。
数据卷主要为了解决:Docker容器产生的数据,那么当容器实例删除后,容器内的数据保存进宿主机的磁盘中了,仍在还在。
特点:
1:数据卷可在容器之间共享或重用数据
2:卷中的更改可以直接实时生效,爽
3:数据卷中的更改不会包含在镜像的更新中
4:数据卷的生命周期一直持续到没有容器使用它为止
2.使用数据卷
docker在容器中管理数据主要有两种方式:
-
数据卷(Volumes)
-
挂载主机目录(Bind mounts)
2.1挂载主机目录
命令如下:
docker run -it --name 容器名 -v 主机目录:容器内目录 镜像名
案例:使用挂载创建并运行一个centos容器
docker run -it --name centos01 -v /Users/test/docker/centos01:/home centos /bin/bash
这样容器里的home文件夹就和主机上/Users/test/docker/centos01的目录同步了
可以inspect查看容器信息里面的挂载信息
docker inspect 5a051379b25f
# 查到Mounts的信息,Source为主机地址,Destination为容器内地址
"Mounts": [
{
"Type": "bind",
"Source": "/Users/fltech/docker/centos01",
"Destination": "/home",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
在主机上创建一个测试文件
test@testdeMacBook-Pro centos01 % touch test.py
到容器内的home目录下查看
[root@5a051379b25f /]# cd home
[root@5a051379b25f home]# ls
test.py
相反,容器内文件发生变化,主机内也会变化。当容器停止后,重新启动,数据依然还在。
注意:
Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个–privileged=true参数即可,如:
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,
在SELinux里面挂载目录被禁止掉了,如果要开启,我们一般使用–privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。
2.2挂载文件读写权限
Docker挂载主机目录的默认权限是读写,用户也可以指定为只读。
ro是只读权限,容器无法修改文件,rw是读写权限,容器可正常读写文件。
可读写命令如下:
docker run -it -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
只读命令如下:
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
2.3数据卷
数据卷也可以单独创建,先不挂载到某个容器,命令如下:
docker volume create mydata
查看所有数据卷
docker volume ls
查看数据卷信息
docker volume inspect mydata
挂载
docker run --name xxxx -p 8888:8888 -v /my:/docker -it imagename /bin/bash
2.4具名挂载和匿名挂载
(1)匿名挂载
在指定数据卷的时候,不指定容器路径对应的主机路径,对应映射的主机路径就是默认的路径/var/lib/docker/volumes/中自动生成一个随机命名的文件夹。
docker run -d --name nginx02 -v /etc/nginx nginx
# 只指定了容器内的目录
可以查看所有的卷
test@testdeMacBook-Pro data % docker volume ls
DRIVER VOLUME NAME
local 5b26a2c0eafe394e55f0b27153bc7edddd4a7398d7c94eb321469c91ee7a3124
(2)具名挂载
在指定数据卷的时候,指定容器路径对应的主机路径,或数据卷名。
docker run -d --name nginx03 -v juming:/etc/nginx nginx
主机文件地址没写绝对路径,只是给数据卷起了名字叫juming
test@testdeMacBook-Pro data % docker volume ls
DRIVER VOLUME NAME
local 5b26a2c0eafe394e55f0b27153bc7edddd4a7398d7c94eb321469c91ee7a3124
local juming
查看卷的信息
test@testdeMacBook-Pro data % docker volume inspect juming
[
{
"CreatedAt": "2021-11-27T07:38:40Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming/_data",
"Name": "juming",
"Options": null,
"Scope": "local"
}
]
所有docker容器内的卷,没有指定目录的情况下,都是在/var/lib/docker/volumes/juming/_data
3.数据挂载继承
挂载继承,就是某个容器启动时可以指定挂载的路径继承自另一个容器,命令如下:
docker run -d --volumes-from 要同步的容器名 镜像名
可以多个容器之间互相挂载,且删除其中一个容器,其他容器文件和宿主机文件都还在。
比如可以多个mysql实现数据共享:
# 启动mysql01 容器与主机挂载
docker run -d --name mysql01 -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
# 指定mysql02容器挂载文件继承自mysql01容器
docker run -d --name mysql02 -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --volumes-from mysql01 mysql
4.案例:mysql数据挂载
运行容器,挂载目录,配置密码
docker run -d --name mysql01 -p 3310:3306 -v /Users/fltech/docker/mysql01/conf:/etc/mysql/conf.d -v /Users/fltech/docker/mysql01/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql
启动成功后,连接测试成功。
把容器停止删除,本地数据仍然在。实现了容器数据持久化。