Dockerfile 指令 VOLUME 介绍
在介绍VOLUME指令之前,我们来看下如下场景需求:
1)容器是基于镜像创建的,最后的容器文件系统包括镜像的只读层+可写层,容器中的进程操作的数据持久化都是保存在容器的可写层上。一旦容器删除后,这些数据就没了,除非我们人工备份下来(或者基于容器创建新的镜像)。能否可以让容器进程持久化的数据保存在主机上呢?这样即使容器删除了,数据还在。
2)当我们在开发一个web应用时,开发环境是在主机本地,但运行测试环境是放在docker容器上。
这样的话,我在主机上修改文件(如html,js等)后,需要再同步到容器中。这显然比较麻烦。
3)多个容器运行一组相关联的服务,如果他们要共享一些数据怎么办?
对于这些问题,我们当然能想到各种解决方案。而docker本身提供了一种机制,可以将主机上的某个目录与容器的某个目录(称为挂载点、或者叫卷)关联起来,容器上的挂载点下的内容就是主机的这个目录下的内容,这类似linux系统下mount的机制。 这样的话,我们修改主机上该目录的内容时,不需要同步容器,对容器来说是立即生效的。 挂载点可以让多个容器共享。
下面我们来介绍具体的机制。
一、通过docker run命令
1、运行命令:docker run --name test -it -v /home/xqh/myimage:/data ubuntu /bin/bash
其中的 -v 标记 在容器中设置了一个挂载点 /data(就是容器中的一个目录),并将主机上的 /home/xqh/myimage 目录中的内容关联到 /data下。
这样在容器中对/data目录下的操作,还是在主机上对/home/xqh/myimage的操作,都是完全实时同步的,因为这两个目录实际都是指向主机目录。
2、运行命令:docker run --name test1 -it -v /data ubuntu /bin/bash
上面-v的标记只设置了容器的挂载点,并没有指定关联的主机目录。这时docker会自动绑定主机上的一个目录。通过docker inspect 命令可以查看到。

xqh@ubuntu:~/myimage$ docker inspect test1
[
{
"Id": "1fd6c2c4bc545163d8c5c5b02d60052ea41900a781a82c20a8f02059cb82c30c",
.............................
"Mounts": [
{
"Name": "0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01",
"Source": "/var/lib/docker/volumes/0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01/_data",
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true
}
],
...........................

上面 Mounts下的每条信息记录了容器上一个挂载点的信息,"Destination" 值是容器的挂载点,"Source"值是对应的主机目录。
可以看出这种方式对应的主机目录是自动创建的,其目的不是让在主机上修改,而是让多个容器共享。
二、通过dockerfile创建挂载点
上面介绍的通过docker run命令的-v标识创建的挂载点只能对创建的容器有效。
通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点。
还有一个区别是,通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。
#test
FROM ubuntu
MAINTAINER hello1
VOLUME ["/data1","/data2"]
上面的dockfile文件通过VOLUME指令指定了两个挂载点 /data1 和 /data2.
我们通过docker inspect 查看通过该dockerfile创建的镜像生成的容器,可以看到如下信息

"Mounts": [
{
"Name": "d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21",
"Source": "/var/lib/docker/volumes/d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21/_data",
"Destination": "/data1",
"Driver": "local",
"Mode": "",
"RW": true
},
{
"Name": "6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36",
"Source": "/var/lib/docker/volumes/6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36/_data",
"Destination": "/data2",
"Driver": "local",
"Mode": "",
"RW": true
}
],

可以看到两个挂载点的信息。
三、容器共享卷(挂载点)
docker run --name test1 -it myimage /bin/bash
上面命令中的 myimage是用前面的dockerfile文件构建的镜像。 这样容器test1就有了 /data1 和 /data2两个挂载点。
下面我们创建另一个容器可以和test1共享 /data1 和 /data2卷 ,这是在 docker run中使用 --volumes-from标记,如:
可以是来源不同镜像,如:
docker run --name test2 -it --volumes-from test1 ubuntu /bin/bash
也可以是同一镜像,如:
docker run --name test3 -it --volumes-from test1 myimage /bin/bash
上面的三个容器 test1 , test2 , test3 均有 /data1 和 /data2 两个目录,且目录中内容是共享的,任何一个容器修改了内容,别的容器都能获取到。
四、最佳实践:数据容器
如果多个容器需要共享数据(如持久化数据库、配置文件或者数据文件等),可以考虑创建一个特定的数据容器,该容器有1个或多个卷。
其它容器通过--volumes-from 来共享这个数据容器的卷。
因为容器的卷本质上对应主机上的目录,所以这个数据容器也不需要启动。
如: docker run --name dbdata myimage echo "data container"
说明:有个卷,容器之间的数据共享比较方便,但也有很多问题需要解决,如权限控制、数据的备份、卷的删除等。这些内容后续文章介绍。
Dockerfile 指令 VOLUME 介绍的更多相关文章
- docker学习笔记18:Dockerfile 指令 VOLUME 介绍
在介绍VOLUME指令之前,我们来看下如下场景需求: 1)容器是基于镜像创建的,最后的容器文件系统包括镜像的只读层+可写层,容器中的进程操作的数据持久化都是保存在容器的可写层上.一旦容器删除后,这些数 ...
- docker学习笔记17:Dockerfile 指令 ONBUILD介绍
ONBUILD指令可以为镜像添加触发器.其参数是任意一个Dockerfile 指令. 当我们在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A ...
- docker学习笔记12:Dockerfile 指令 ENTRYPOINT介绍
本文介绍Dockerfile的 ENTRYPOINT指令的含义. 先回顾下CMD指令的含义,CMD指令可以指定容器启动时要执行的命令,但它可以被docker run命令的参数覆盖掉. ENTRYPOI ...
- docker学习笔记14:Dockerfile 指令 ENV介绍
ENV指令用来在镜像构建过程中设置环境变量.我们来看一个Dockerfile的例子: #test FROM ubuntu MAINTAINER hello ENV MYDIR /mydir RUN m ...
- docker学习笔记13:Dockerfile 指令 WORKDIR介绍
Dockerfile中的WORKDIR指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行. 相当于设置容器的工作目录了.我们来看一个dockerfile文件 #test FROM ub ...
- docker学习笔记11:Dockerfile 指令 CMD介绍
我们知道,通过docker run 创建并启动一个容器时,命令的最后可以指定容器启动后在容器内立即要执行的指令,如: docker run -i -t ubunu /bin/bash //表示容器 ...
- Dockerfile 指令 WORKDIR介绍
Dockerfile中的WORKDIR指令用于指定容器的一个目录, 容器启动时执行的命令会在该目录下执行. 相当于设置容器的工作目录了.我们来看一个dockerfile文件 #test FROM ub ...
- docker学习笔记15:Dockerfile 指令 USER介绍
USER指令用于指定容器执行程序的用户身份,默认是 root用户. 在docker run 中可以通过 -u 选项来覆盖USER指令的设置. 举例:docker run -i -t -u mysql ...
- Docker学习(三): Dockerfile指令介绍
特别声明: 博文主要是学习过程中的知识整理,以便之后的查阅回顾.部分内容来源于网络(如有摘录未标注请指出).内容如有差错,也欢迎指正! =============系列文章============= 1 ...
随机推荐
- linux 运维,代理,acl控制访问
运维概述:运行 & 维护,Operation & MaintanceIT运维.业务运维.日常管理运维采用相关的方法.手段.技术.制度.流程和文档等,对IT运行环境.IT业务系统和IT运 ...
- 笔记︱风控分类模型种类(决策、排序)比较与模型评估体系(ROC/gini/KS/lift)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 本笔记源于CDA-DSC课程,由常国珍老师主讲 ...
- Android可以拖动位置的ListVeiw
参考网址: 1.https://github.com/bauerca/drag-sort-listview 2.http://www.tuicool.com/articles/jyA3MrU
- Redis相关指令文档
连接控制 QUIT 关闭连接 AUTH (仅限启用时)简单的密码验证 适合全体类型的命令 EXISTS key 判断一个键是否存在;存在返回 1;否则返回0; DEL key 删除某个key,或是一系 ...
- R语言︱构造新序列
1.数值构造函数rep与seq #数值构造rep与seq rep(1:4,each=2)#依次重复1:4两遍 rep(1:4,2) #注意,重复1:4两遍 seq(from=3,to=5,by=0.2 ...
- SQLyog键盘快捷方式
SQLyog键盘快捷方式 连接 Ctrl+M 创建新连接 Ctrl+N 以当前连接属性创建新连接 Ctrl+F4/Ctrl+W 断开当前连接 Ctrl+Tab 切换到下一个连接 Ctrl+Shift+ ...
- Netty的并发编程实践1:正确使用锁
很多刚接触多线程编程的开发者,虽然意识到了并发访问可变变量需要加锁,但是对于锁的范围.加锁的时机和锁的协同缺乏认识,往往会导致出现一些问题.下面笔者就结合Netty的代码来讲解下这方面的知识. 打开F ...
- freemarker报错之十三
1.错误描述 freemarker.core.ParseException: Token manager error: freemarker.core.TokenMgrError: Unknown d ...
- (八)java垃圾回收和收尾
垃圾回收机制:当一个对象不再被引用时,或者说当一个对象的引用不存在时,我们就认为该对象不再被需要,它所占用的内存就会被释放掉. 垃圾回收只是在程序执行过程中偶尔发生,java不同的运行时刻会产 ...
- CentOS 7离线安装MySQL 5.7
系列文章首发平台为果冻想个人博客.果冻想,是一个原创技术文章分享网站.在这里果冻会分享他的技术心得,技术得失,技术人生.我在果冻想等待你,也希望你能和我分享你的技术得与失,期待. 前言 网上已经有那么 ...