在介绍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"

说明:有个卷,容器之间的数据共享比较方便,但也有很多问题需要解决,如权限控制、数据的备份、卷的删除等。这些内容后续文章介绍。

docker学习笔记18:Dockerfile 指令 VOLUME 介绍的更多相关文章

  1. Docker学习笔记三 Dockerfile 指令 定制镜像

    本文地址:https://www.cnblogs.com/veinyin/p/10412079.html  镜像是分层存储的,每一层都是独立存在的,修改当前层并不会修改其依赖的上一层,删除某一层也只是 ...

  2. Dockerfile 指令 VOLUME 介绍

    在介绍VOLUME指令之前,我们来看下如下场景需求: 1)容器是基于镜像创建的,最后的容器文件系统包括镜像的只读层+可写层,容器中的进程操作的数据持久化都是保存在容器的可写层上.一旦容器删除后,这些数 ...

  3. Docker学习笔记之Dockerfile

    Dockerfile的编写格式为<命令><形式参数>,命令不区分大小写,但一般使用大写字母.Docker会依据Dockerfile文件中编写的命令顺序依次执行命令.Docker ...

  4. Docker学习笔记_Dockerfile常用指令

    Dockerfile常用指令

  5. Docker学习笔记总结

    Docker学习笔记 https://yeasy.gitbooks.io/docker_practice/content/   一 环境搭建 Ubuntu安装 .添加软件源的GPG密钥 curl -f ...

  6. docker学习笔记(3)- 镜像

    简介 在docker学习笔记(1)- 架构概述一节中可以看到镜像是docker三大组件之一,可以将Docker镜像类比为虚拟机的模版. 镜像由多个层组成,每层叠加之后从外部看就像一个独立的对象,镜像的 ...

  7. docker~学习笔记索引

    回到占占推荐博客索引 使用docker也有段时间了,写了不少文章与总结,下面把它整理个目录出来,方便大家去学习与检索! docker~学习笔记索引 docker~linux下的部署和基本命令(2017 ...

  8. Docker学习笔记之-部署.Net Core 3.1项目到Docker容器,并使用Nginx反向代理(CentOS7)(一)

    上一节演示如何安装Docker,链接:Docker学习笔记之-在CentOS中安装Docker 本节演示 将.net core 3.1 部署到docker容器当中,并使用 Nginx反向代理,部署平台 ...

  9. docker学习笔记1 -- 安装和配置

    技术资料 docker中文官网:http://www.docker.org.cn/ 中文入门课程:http://www.docker.org.cn/book/docker.html docker学习笔 ...

随机推荐

  1. javascript的isPrototypeOf函数的理解

    JavaScript中isPrototypeOf函数方法是返回一个布尔值,指出对象是否存在于另一个对象的原型链中.使用方法: object1.isPrototypeOf(object2)~~~原型链理 ...

  2. SIGAR - System Information Gatherer And Reporter

    https://support.hyperic.com/display/SIGAR/Home 收藏一篇: http://www.cnitblog.com/houcy/archive/2012/11/2 ...

  3. 一键搜索之Win10锁屏壁纸

    前天无意发现win10的锁屏壁纸挺漂亮的,就想着能不能保存下来?网上一搜果然有资料,当时参考的连接如下 http://jingyan.baidu.com/article/fedf07375ea2513 ...

  4. 编译和安装shibboleth-sp遇到的问题

    In file included from mod_shib_20.cpp:68: mod_shib.cpp:118: warning: deprecated conversion from stri ...

  5. react的初涉入

    1.react并不是一个完整的MVC,MVVM框架 它只负责view层 2.react跟Web Components不冲突 3.react的特点是“轻” 4.react用组件的方式重新思考构建UI的过 ...

  6. use MSBuild cmd to build and deploy the database project.

    You can use the below command to implement it. SET TargetDBName="Database name" SET DataBa ...

  7. 简单字符串模式匹配算法的C++实现

    /* * simpleIndex.cpp * Author: Qiang Xiao * Time: 2015-07-13 */ #include<iostream> #include< ...

  8. WRTnode 的 HTTP Web 开关实验(2016-05-16)

    前言 这里是节取自 物联网的任意门——WRTnode2R 评测 中的 http web 开关灯实验,所以有一些前置设置如果没有描述清楚可参考该处. 正文 步骤一:编辑一个 html 文件,放在 /ww ...

  9. 如何去掉Protel99se汉化菜单

    说明: 安装Protel99se汉化包后,卸载后重新安装也无法去掉汉化菜单.本文介绍解决办法. 问题: 网上一些Protel99se的安装包内,在介绍Protel安装时,采用3大步的方法.第一步安装P ...

  10. JAVA GUI学习 - 窗体背景图片设置方法:重写paintComponent(Graphics g)方法

    public class BackgroundImage extends JFrame { public BackgroundImage() { this.setTitle("窗体背景图片设 ...