所谓的 Docker 数据持久化,也就是数据不会随着容器的结束而删除,对于像数据库这类的应用,为了能够使数据持久化,提供了 Volume 的概念,简单来说,就是可以绕过默认的联合文件系统,将文件或者目录保存在宿主机上。
通常有两种:A) Bind Mount 保存在主机上的某个目录;B) Volume 通过 Docker 自己管理的 Volume 。
Bind Mount
在很早就已经开始使用了,将主机的目录挂载到容器中,不过在不同的操作系统中无法移植,所以不会出现在 Dockerfile 中。
# docker run -it -v $(pwd)/host-data:/container-data alpine sh
将主机上当前目录下的 host-data
目录挂载到容器的 /container-data
目录。注意,本地的目录必须使用绝对路径(不存在则自动生成),否则会被识别为 Volume ,而且容器中同样强制使用绝对路径。
Volume
同样也是绕过容器的文件系统,直接将数据写到主机上,只是 volume 是被容器管理的,默认所有的 volume 都在主机的 /var/lib/docker/volumes
目录下。
# docker run -it -v host-volume:/container-data alpine sh
将 host-volume
挂载到容器的 /container-data
目录,此时会默认创建一个 host-volume
,然后,可以通过如下命令查看 Volume 信息。
# docker volume inspect host-volume
[
{
"CreatedAt": "2019-7-29T11:18:24+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/host-volume/_data",
"Name": "host-volume",
"Options": null,
"Scope": "local"
}
]
如果在启动时只使用 -v /container-data
参数,那么会创建一个匿名的 Volume ,一般默认的路径为 /var/lib/docker/volumes/<ID>/_data
。
常用命令
----- 创建、删除、查看Volume
# docker volume create
# docker volume rm
# docker volume ls
----- 查看详细参数
# docker volume inspect
----- 清理不需要的Volumes
# docker volume prune
注意事项
创建目录
如果在容器内创建目录,那么目录的元数据中保存的是 UID:GID
信息,所以,如果容器和宿主机之前的映射关系不同,那么通过 ls
查看时就会显示不同的用户名。
权限问题
挂载宿主机已经存在的目录,如果修改目录下的内容可能会报 Permission denied
的错误,可以通过如下方式尝试修改。
----- 关闭SELinux配置,如下包括了临时关闭和永久关闭,最终确认是否关闭
# setenforce 0
# vim /etc/sysconfig/selinux
SELINUX=disabled
# getenforce
Disabled
----- 以特权方式启动容器
# docker run -it --privileged=true -v /test:/soft centos /bin/bash