前言:数据卷和挂载还不是一回事,不过都可以实现数据分离:Link

附带例子的第一条,命令属于挂载:用docker volume ls是查不到的。

附带例子的第二、三条,命令属于使用数据卷:用docker volume ls可以查看。

卷的使用

创建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,挂载之后及时容器删除,宿主机的目录不变,除非手动删除卷数据。

清理所有无用数据卷:docker volume prune  。有些删除的容器还会有卷的残留

运行时挂载

使用命名卷

有了 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"

//使用docker卷自动维护的方式(数据卷方式,自定义卷名)
docker run -p 80:80 -p 88:88 -i -t -d  -v upload:/var/www/html/jsontest/upload -v mysql:/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
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐