Docker卷(volume)的使用,挂载宿主机目录到容器目录,实现docker数据存储分离
卷的使用
创建volume:docker volume create vol_name
查看volume:docker volume ls
可以看到当前存在的所有的 volume。
删除volume:docker volume rm
删除指定的 volume。
查看volume详情:docker volume inspect vol_name
可以看到它的详情,包括创建时间和宿主机上的真正挂载位置等。
可以看到这个新建的 vol_name
保存在 /var/lib/docker/volumes/vol/_data
下,其中 /var/lib/docker/volumes
目录保存了所有的 Docker volume,挂载之后及时容器删除,宿主机的目录不变,除非手动删除卷数据。
运行时挂载
使用命名卷
有了 volume 之后,我们便可以使用刚才创建的 vol 来挂载容器中的某个目录:
docker run -d -v vol:/data --name temp-redis redis
如此一来,在 temp-redis 容器中 /data
下的改动,都会同步反映在宿主机的 /var/lib/docker/volumes/vol/_data
下;而宿主机的改动亦然。
使用绝对路径
使用命名的 volume 通常是为了数据共享,很多时候我们只是想指定一个挂载的目录便于记忆和管理,这个时候可以使用绝对路径,如:
docker run -d -v /data/docker_volume/temp_redis/data:/data --name temp-redis redis
自动挂载
有时候你甚至不想关心任何 volume 的形式,你只是想把某个目录持久化而已,可以这么做:
docker run -d -v /data --name temp-redis redis
Docker 会自动生成一个匿名的 volume。想要知道具体的宿主机目录可以使用:docker inspect
来查看。这种情况通常在构建纯数据容器时使用。
注意点
在 volume 创建时和创建之后仍然需要关注他们,下面是一些典型的问题。
volume 自动创建
事实上在 -v vol:/data
时候,vol volume 甚至不需要提前使用 docker volume create vol
创建,使用 docker run -v vol:/data
命令时便会自动创建。
同时地,也意味着 -v
选项不支持相对路径的使用。
volume 的删除
在一个 volume 被创建之后,想删除可没那么容易,即使使用了 docker rm CONTAINER
删除了容器,volume 依然保留着。除非:
- 使用
docker run --rm
启动的容器停止时。它除了会删除容器本身还会删除挂载的匿名 volume。 - 使用
docker rm -v
v 参数可以删除容器和创建容器时关联的匿名 volume。
那么我们在使用了 named volume 或者删除容器时忘记了 -v
,那么那些在 /var/lib/docker/volumes
下的一些文件就成了僵尸文件。怎么删除呢?
- 使用
docker volume rm VOLUME
来删除。 - 使用
docker volume prune
删除所有不再被使用的 volume。
volume 的只读控制
一些场合下,我们提供只是需要容器内的程序去读取一些内容而非修改。我们可以严格的控制 volume,增加只读选项 ro
:
docker run -d \
--name=nginxtest \
-v nginx-vol:/usr/share/nginx/html:ro \
nginx:latest
通过 Dockerfile 挂载
可以通过 Dockerfile 在构建镜像的时候便指定需要的 volume,这对于很多应用都是必要的,尤其是一些数据类应用。
Dockerfile 中使用 VOLUME 表明挂载目录,如:
VOLUME ["/data1", "/data2"]
任何通过该镜像构建的容器都会将 /data1
,/data2
两个目录进行挂载。但是 Dockerfile 形式的弱势是无法进行 named volume 或者绝对路径的挂载。
数据共享与存储
共享 volume
既然数据可以在宿主机和容器间同步,那么可以使多个容器间同步吗?当然可以!
1、–volumes-from
# 首先创建一个容器,并挂载 /data
docker run -d -v /data --name ng1 nginx
# 创建第二个容器,共享前者的 volume
docker run -d --volumes-from ng1 --name gn2 nginx
2、named volume
# 首先创建一个容器,并创建命名卷 share 来挂载 /data
docker run -d -v share:/data --name ng1 nginx
# 创建第二个容器,使用同样的 /data
docker run -d -v share:/data --name ng2 nginx
两种方式都能达到数据共享的目的,但是由于通过命名卷的方式对多个容器的依赖进行了解耦,所以推荐第二种。
数据容器
这个话题事实上和数据共享紧密相关,由于在 Docker1.9 之前,大家广泛使用使用 --volumes-from
的形式来共享卷,导致必须要一个底层的没有依赖的容器来保存数据。
- 通常使用和应用容器一样的镜像来构建数据容器
- 数据容器不需要也不应该启动,仅仅是利用 volume 机制来保持数据而已
然而现在有了命名卷,完全不需要数据容器的存在了,使用 named volume 可以更直接更方便的管理共享数据。
附带:
语法:
docker run -it -v HOSTDIR:VOLUMEDIR images
我自己项目使用的命令,创建容器时挂载共享目录,宿主机作为docker的数据盘,多个-v 可以共享多个目录,我还将数据库的数据保存到宿主机。
//自定义存储目录
docker run -p 80:80 -p 88:88 -i -t -d -v /data/jsontest/upload:/var/www/html/jsontest/upload -v /data/mysql:/var/lib/mysql --restart=always computercenter:v5.3.0 /bin/bash -c "/etc/rc.local; /bin/bash"
//使用docker卷自动维护的方式
docker run -p 80:80 -p 88:88 -i -t -d -v /var/www/html/jsontest/upload -v /var/lib/mysql --restart=always computercenter:v5.3.0 /bin/bash -c "/etc/rc.local; /bin/bash"
卷的使用
参考1:Link
参考2:Link
Docker 空间使用分析与清理
参考:Link
Docker 的内置 CLI 指令 docker system df 【-v】,可用于查询镜像(Images)、容器(Containers)和本地卷(Local Volumes)等空间使用大户的空间占用情况。
Docker 实践简明指南
参考:Link
docker之如何挂载一个容器已经存在(有文件)的目录
参考:Link
原来不加-it就可以建完容器再挂载。
先正常启动 docker ruql -it -p 80:80 hofmann/zentao
把mysql数据库文件拷贝出来/tmp/zen$ sudo docker cp c3f2:/opt/zbox/data/mysql .
再通过挂载的方式启动就可以了/Desktop$ docker run -v /tmp/zen/mysql:/opt/zbox/data/mysql -it -p 80:80 hofmann/zentao