引言

docker的镜像是由多个只读的文件系统叠加在一起形成的。当我们在我启动一个容器的时候,docker会加载这些只读层并在这些只读层的上面(栈顶)增加一个读写层。这时如果修改正在运行的容器中已有的文件,那么这个文件将会从只读层复制到读写层。该文件的只读版本还在,只是被上面读写层的该文件的副本隐藏。当删除docker,或者重新启动时,之前的更改将会消失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System联合文件系统)。

为了很好的实现数据保存和数据共享,Docker提出了Volume这个概念,简单的说就是绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷

Volume的作用

  • 通过数据卷可以在容器之间实现共享和重用
  • 对数据卷的修改会立马生效(非常适合作为开发环境)
  • 对数据卷的更新,不会影响镜像
  • 卷会一直存在,直到没有容器使用

初始化Volume

在使用docker run的时候我们可以通过 -v 来创建一个数据卷并挂载到容器上,在一次run中多次使用可以挂载多个容器。

如果使用Dockerfile方式进行初始化时可以使用 VOLUME 来添加一个或者多个新的卷到由该镜像创建的任意容器。

创建一个数据卷

docker run -p : -d --name shanlei-nginx -v /usr/share/nginx/html nginx

上面的命令的意思是,我们创建了一个名称为shanlei-nginx的容器,将本机的8080端口映射到容器中nginx服务器的默认web访问端口80下,创建一个数据卷,并挂载到容器的/usr/share/nginx/html目录下。

这时我们就可以绕过联合文件系统,直接在主机上操作该目录了,任何在该镜像/usr/share/nginx/html下的文件都会被复制到Volume。

我们可以通过docker inspect指令找到Volume在主机上的存储位置

docker inspect inspect shanlei-nginx

docker inspect指令后面的参数可以跟容器名称。通过这个命令我们可以获得容器所有的相关信息。我们需要看这一部分

...
... "Mounts": [
{
"Type": "volume",
"Name": "057f911105d4c77d2cfe16ee6acb7f5a43f2643d571708da40f5db55e27b1155",
"Source": "/var/lib/docker/volumes/057f911105d4c77d2cfe16ee6acb7f5a43f2643d571708da40f5db55e27b1155/_data",
"Destination": "/usr/share/nginx/html",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...
...

这说明docker把本机的“Source”指向目录,也就是

/var/lib/docker/volumes/057f911105d4c77d2cfe16ee6acb7f5a43f2643d571708da40f5db55e27b1155/_data

挂载到了容器的“Destination”指向的目录。

在Linux中我们可以直接进入“Source”指向的路径(注意在访问该目录时可能会有权限问题)

只要将主机的目录挂载到容器的目录上,那改变就会立即生效。在Dockerfile中我们可以通过VOLUME达到相同的目的

FROM nginx
VOLUME /usr/share/nginx/html

目录作为数据卷

通过-v标识可以将主机的目录挂载到容器中去

sudo docker run -d -p : -v $PWD/html:/usr/share/nginx/html nginx

上面的命令将本机的$PWD/html目录挂载到容器的/usr/share/nginx/html目录。$PWD在是一个系统环境变量,指代当前目录环境。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动为你创建它。

注意:Dockerfile中不支持这种语法.

docker挂载数据卷的默认权限是读写,当然我们可以通过指令:ro指定为只读。

sudo docker run -d -p : -v $PWD/html:/usr/share/nginx/html:ro nginx

在我的本机主机的$PWD/html中有一个index.html文件,内容如下:

this is old

我们运行上面的命令,并将本机8080端口映射到容器中nginx服务器的默认web端口80下,现在我们来访问localhost:8080

现在我们修改本机下的$PWD/html/index.html

this is new

访问localhost:8080

文件作为数据卷

我们也可以使用-v指令从主机挂载单个文件到容器中去

docker run -d -p : -v $PWD/html/index.html:/usr/share/nginx/html/index.html nginx

当修改本机$PWD/html/index.html时,容器中的/usr/share/nginx/html/index.html也会随之变化。效果和上面相同,在这里就不做赘述了。

注意:如果直接挂载一个文件,很多文件编辑工具,包括 vi 或者 sed --in-place ,可能会造成文件 inode的改变,从 Docker 1.1 .0起,这会导致报错误信息。所以最简单的办法就直接挂载文件的父目录。

数据共享

如果想要实现容器间的数据共享,那么需要授权一个容器访问另一个容器的Volume。我们可以在使用docker run时使用-volumes-from参数来进行指定。

docker run -it -h NEWCONTAINER --volumes-from shanlei-nginx ubuntu /bin/bash

注意:值得注意的是不管shanlei-nginx是否运行,它都会起作用。只要有容器连接Volume,它就不会被删除。

数据卷容器

如果我们有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。常见的使用场景是使用纯数据容器来持久化数据库、配置文件或者数据文件等。

数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。

首先我们需要先创建一个数据卷容器

docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres

然后通过--volumes-from指令参数来挂载 dbdata 容器中的数据卷。

docker run -d --volumes-from dbdata --name db1 training/postgres

当然,我们也可以使用多个 --volumes-from 参数来从多个容器挂载多个数据卷。 也可以从其他已经挂载了数据卷的容器
来挂载数据卷。

docker run -d --name db3 --volumes-from db1 training/postgres

现在我们进入容器中查看数据卷容器是否挂载成功

docker exec -it db1 /bin/bash

说明数据卷容器挂载已经成功了。

注意:如果删除了挂载的容器(包括 dbdata、db1 和 db2等),数据卷并不会被自动删除。如果要删除一个数据卷,必
须在删除最后一个还挂载着它的容器时使用 docker rm -v 命令来指定同时删除关联的容器。

备份和恢复

我们可以利用数据卷对其中的数据进行进行备份、恢复和迁移。

首先使用 --volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从本地主机挂载当前到容器的 /backup 目录。命令如下:

docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

容器启动后,使用了 tar 命令来将 dbdata 卷备份为本地的 /backup/backup.tar 。

恢复

如果要恢复数据到一个容器,首先创建一个带有数据卷的容器 dbdata2。

docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

然后创建另一个容器,挂载 dbdata2 的容器,并使用 untar 解压备份文件到挂载的容器卷中。

docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar

以上

docker进阶篇(一) ---- Volume(数据卷)的更多相关文章

  1. Docker容器学习梳理 - Volume数据卷使用

    之前部署了Docker容器学习梳理--基础环境安装,接下来看看Docker Volume的使用. Docker volume使用 Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker ...

  2. Docker(六)容器数据卷

    容器数据卷 docker的理念回顾 将应用和环境打包成一个镜像 需求:数据可以持久化和同步 使用数据卷 指定路径挂载 docker run -it -v 主机目录:容器内目录 # 测试 [root@h ...

  3. Docker系列(20)- 数据卷容器

    数据卷容器 什么是数据卷容器? 容器和容器之间实现数据共享 一个容器先于宿主机创建挂载方式,宿主机就会有改卷的目录 第二个容器使用命令--volumes-from 第一个容器,共享使用了第一个容器与宿 ...

  4. docker挂载本地目录和数据卷容器

    1.docker挂载本地目录 docker可以支持把一个宿主机上的目录挂载到镜像里. 交互模式运行docker run -it -v /home/dock/Downloads:/usr/Downloa ...

  5. Docker——网络和存储(数据卷)

    iptables -t nat -vnL |grep docker 查看docker桥接网卡:brctl show 本地端口随机映射到docker容器的80端口上: docker run -d -P ...

  6. Docker系列(19)- 数据卷之Dockerfile

    初识Dockerfile Dockerfile就是用来构建docker镜像的构建文件!命令脚本! 通过这个脚本生成镜像,镜像是一层一层的,脚本与一个个的命令,每个命令都是一层! # 创建一个docke ...

  7. docker 数据卷之进阶篇

    笔者在<Docker 基础 : 数据管理>一文中介绍了 docker 数据卷(volume) 的基本用法.随着使用的深入,笔者对 docker 数据卷的理解与认识也在不断的增强.本文将在前 ...

  8. docker 数据卷 ---- 进阶篇

    笔者在<Docker 基础 : 数据管理>一文中介绍了 docker 数据卷(volume) 的基本用法.随着使用的深入,笔者对 docker 数据卷的理解与认识也在不断的增强.本文将在前 ...

  9. docker学习5--docker数据卷(volume)

    https://blog.csdn.net/dream_broken/article/details/52314993 1.什么是数据卷volume 为了了解什么是Docker Volume,首先我们 ...

随机推荐

  1. netty(一) netty有哪几部分构成

    netty netty是一个支持高并发的非阻塞I/O框架. Channel Channel 是 NIO 基本的结构.它代表了一个用于连接到实体如硬件设备.文件.网络套接字或程序组件,能够执行一个或多个 ...

  2. CentOS7配置samba服务

    Step1:安装samba相关软件 [root@node-1 ~]# yum -y install samba samba-client Step2:创建共享目录 [root@node-1 ~]# m ...

  3. react官方脚手架搭建项目

    1.全局安装 npm install -g create-react-app 2. app后面还要给项目文件命名 create-react-app //是全局命令来创建react项目 3.然后按照提示 ...

  4. 【读书笔记】深入应用C++11代码优化与工业级应用 读书笔记01

    第一章 使用C++11让程序更简洁.更现代 1.1  类型推导 1.1.1  auto类型推导 1.auto关键字的新意义 不同于python等动态类型语言的运行时进行变量类型的推导,隐式类型定义的类 ...

  5. python note 03 切片及对字符串操作

    1.计算 1 - 2 + 3 ... + 99 中除了88以外的数之和 i = 1 sum = 0 while i < 100 : if i == 88 : i = i + 1 continue ...

  6. python中type、class、object之间的关系

    先看一段代码 # -*- coding:UTF-8 -*- __autor__ = 'zhouli' __date__ = '2018/11/13 18:40' a = 1 b = 'abc' pri ...

  7. sed原理及使用

    前言 环境:centos6.5 sed版本:GNU sed version 4.2.1 本文的代码都是在这个环境下验证的. 一.简介 sed(Stream Editor)意为流编辑器,是Unix常见的 ...

  8. thinkphp 查表返回的数组,js解析有UNICode编码,解决办法

    public function getDeviceMsg(){ $allDevicesMsg = M("newdevicesstatus")->getField(" ...

  9. Quartz.Net进阶之一:初识Job作业和触发器

        前几天写了一篇有关Quartz.Net入门的文章,大家感觉不过瘾,想让我在写一些比较深入的文章.其实这个东西,我也是刚入门,我也想继续深入了解一下,所以就努力看了一些资料,然后自己再整理和翻译 ...

  10. [BeijingWc2008]雷涛的小猫

    --BZOJ1270 Description 雷涛的小猫雷涛同学非常的有爱心,在他的宿舍里,养着一只因为受伤被救助的小猫(当然,这样的行为是违反学生宿舍管理条例的). 在他的照顾下,小猫很快恢复了健康 ...