GVKun编程网logo

用一个实际例子理解 Docker volume 工作原理(docker的volume是什么用)

7

最近很多小伙伴都在问用一个实际例子理解Dockervolume工作原理和docker的volume是什么用这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展Docker-命令-doc

最近很多小伙伴都在问用一个实际例子理解 Docker volume 工作原理docker的volume是什么用这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展Docker - 命令 - docker volume、Docker - 命令 - volume 相关、docker -v 和Dockerfile 中VOLUME 区别、Docker 0x06: Docker Volume卷等相关知识,下面开始了哦!

本文目录一览:

用一个实际例子理解 Docker volume 工作原理(docker的volume是什么用)

用一个实际例子理解 Docker volume 工作原理(docker的volume是什么用)

要了解 Docker Volume,首先我们需要理解 Docker 文件系统的工作原理。Docker 镜像是由多个文件系统的只读层叠加而成。当一个容器通过命令 docker run 启动时,Docker 会加载只读镜像层并在镜像栈顶部添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,但是该文件的只读版本依然存在,只不过已经被读写层中该文件的副本所隐藏。

当删除 Docker 容器,并通过该镜像重新启动时,之前在读写层的更改将会丢失。在 Docker 中,只读层及在顶部的读写层的组合被称为 Union File System(联合文件系统),简称 UnionFS,它用到了一个重要的资源管理技术,叫写时复制。写时复制(copy-on-write),也叫隐式共享,是一种对可修改资源实现高效复制的资源管理技术。对于一个重复资源,若不修改,则无需立刻创建一个新的资源,该资源可以被共享使用。当发生修改的时候,才会创建新资源。这会大大减少对于未修改资源复制的消耗。其实 COW 这个概念对编程人员来说一点也不陌生,广泛用在各种领域,比如 ABAP 里对于内表 (Internal table) 的拷贝动作,Java 字符串的拷贝实现等等。Docker 基于 UnionFS 去创建 containers。

我们下面看一个实际例子。

使用命令行 docker run --help 查看这个命令的帮助文档。 -h 的作用是指定容器的主机名。

使用命令行创建一个新的容器:

docker run -it --name jerry-container-test -h CONTAINER -v /data busybox /bin/sh 名称为 jerry-container-test, 用 - v 创建了一个 volume /data

创建完毕之后,在容器里执行 cd /data 进入这个目录,这个时候还是空的。

docker ps 查看容器状态:

现在我想知道主机上为了实现这个 volume,使用了哪个 internal 目录。

用命令 docker inspect jerry-container-test 查看关键字 "volumes":

得到了容器里 /data 在主机上实现的目录:

/var/lib/docker/volumes/96aa969033ee7e6d7ff607a0a47de5a5866613a422518ed3f86fee6240bae8cc/_data

现在我在主机上使用 touch 命令在这个目录下直接创建一个文件:

sudo touch /var/lib/docker/volumes/96aa969033ee7e6d7ff607a0a47de5a5866613a422518ed3f86fee6240bae8cc/_data/test.s

现在切换到容器里,用 ls 也能看到直接在主机上用 touch 命令在 internal folder 里创建的文件了。

要获取更多 Jerry 的原创文章,请关注公众号 "汪子熙":

Docker - 命令 - docker volume

Docker - 命令 - docker volume

  1. 概述

    1. docker volume 命令
  2. 背景

    1. docker 容器的存储,通常需要独立于镜像
    2. docker volume 就是负责这块的命令

1. 写在 docker volume 之前

  1. 概述

    1. docker run 与 volume 相关的介绍
  2. 背景

    1. 其实在使用 docker [container] run 的时候,我们已经在使用 volume 了
  3. volume

    1. 概述

      1. 类似
        1. linux 里的 卷
        2. windows 里的 盘
    2. 作用

      1. 对接其他设备
      2. 拓展存储空间
      3. 隔离存储区域
      4. 对数据的迁移,复用,也有支持

1. 首先,这个不是 volume

  1. 概述

    1. docker run -v 中,本地目录 与 容器路径 对接,不是 volume
  2. 命令

    > docker run --name some-nginx1 -v $(pwd)/html:/usr/share/nginx/html -d nginx
    
  3. 结果

    1. 容器成功启动
    2. 容器的 ''/usr/share/nginx/html'' 目录,与 宿主机 的 ''$(pwd)/html'' 目录,成功关联
    3. 但是
      1. 并没有创建 volume
  4. 验证

    1. docker container inspect

      1. HostConfig 下
        1. Volumes 字段,值为 null
    2. docker volume ls

      1. 无法查到 新的 volume
  5. 特性

    1. 触发

      1. 填写路径时,需要用以下方式触发
        1. /
        2. ~/
    2. 路径

      1. host 上如果不存在,主动创建
      2. container 上如果不存在,主动创建
    3. 覆盖

      1. 如果冲突,则以 host 为准

2. 然后,我们开始使用 volume

  1. 概述

    1. 在 docker run 中使用 volume
  2. 位置

    1. 路径

      # 默认位置
      /var/lib/docker/volumes
      # 具体位置, 可以通过 docker container inspect 查看
      
  3. 命令

    > docker run --name some-nginx2 -v html:/usr/share/nginx/html -d nginx
    
  4. 结果

    1. 容器启动成功
    2. 在 volume 的默认路径下,创建了一个 volume
      1. 名为 html
    3. html 与 容器的路径 绑定成功
  5. 验证

    1. docker volume ls
      1. 可以查看到新的 volume
  6. 其他

    1. volume 名称
      1. 如果不指定,会随机生成

        > docker run --name some-nginx2 -v /usr/share/nginx/html -d nginx
        
    2. volume 权限
      1. 权限

        1. 只读
        2. 读写
      2. 指定

        # 默认为 rw
        -v html:/usr/share/nginx/html[:ro|:rw]
        

3. volumes-from

  1. 概述

    1. 创建新容器时,使用和另一个容器相同的挂载策略
  2. 场景

    1. 容器 d1
      1. 有自己的卷
    2. 容器 d2
      1. 继承 d1 的卷
  3. 命令

    1. d1

    2. d2

      > docker container run --name d2 --volumes-from d1 -d nginx
      
  4. 埋个坑

    1. 参考里创建 d1 的时候,没有带 -v

      1. 创建 d2 也没问题
      2. docker container inspect 查看时,也能正确查看到
      3. 但是这个继承,到底有没有意义
        1. 还是说,容器起来的时候,临时读写层,也被视为了 volume?
    2. volume 的生命周期

      1. 例子里说了这么个情况
        1. d1 创建,有了 volume v1
        2. d2 volumes-from 了 d1, 使用了 同样的 v1
        3. d1 关闭了,volume 不受影响
        4. d2 关闭,没有容器使用 v1,
        5. 然后 v1 的生命周期结束了
      2. 疑问
        1. 什么是 volume 的生命周期
        2. 我试过所有容器都结束,甚至删掉的情况
          1. -v 创建的卷,依然存在
          2. 那结束,又是怎么个回事

2. docker volume

1. 概述

  1. docker volume 命令
    1. 有了上面的认识,后续的理解,会方便很多

2. 命令们

  1. ls

    1. 概述

      1. 查看卷列表
    2. 命令

      # 返回 driver 信息 和 volume 的名称
      > docker volume ls
      
  2. inspect

    1. 概述

      1. 查看卷详情
    2. 命令

      # 稍微详细的信息, 不细说了
      > docker volume inspect <volumeName>
      
  3. create

    1. 概述

      1. 创建卷
    2. 命令

      # 在默认位置, 创建一个名为 volumeName 的卷
      # 卷 不能重名
      # 创建完之后, 可以用 volumeName 在 创建容器时挂载
      > docker volume crreate <volumeName>
      
  4. rm

    1. 概述

      1. 删除卷
    2. 命令

      # 删除卷
      > docker volume rm <volumeName> 
      
  5. prune

    1. 概述

      1. 删除 闲置卷
    2. 命令

      # 删除没有挂载的卷
      > docker volume prune
      

ps

  1. ref

    1. docker 容器与容器云
      1. 问题
        1. 这本书没把 bind 和 volume 区分得很开
    2. Docker 学习笔记(6)——Docker Volume
      1. advantage
        1. 区分了 bind mount 和 volume
      2. disadvantage
        1. 没有 ref 作为支持
    3. docker 入门 —— docker 容器数据卷 volumes-from
  2. 问题 1: 是否有 mount 之类的命令

    1. 条件
      1. 运行之中
  3. 问题 2: 上面提到的一些问题

    1. 概述
      1. 需要验证
  4. 问题 3: 卷能独立于文件系统

    1. 概述

      1. 在书上看到有书这么说,但是我想不明白
      2. 我所创建的卷,都是在本地,文件系统,是由 /var 那个盘决定的
      3. 如果要触发,需要什么条件
        1. 将 /var 挂载为其他目录
        2. 指定 卷存放的位置,到其他的文件系统
    2. 感觉是个坑,以后得填上

Docker - 命令 - volume 相关

Docker - 命令 - volume 相关

  1. 概述
    1. docker volume 命令
  2. 背景
    1. docker 容器的存储, 通常需要独立于镜像
    2. docker volume 就是负责这块的命令

1. 写在 docker volume 之前

  1. 概述
    1. docker run 与 volume 相关的介绍
  2. 背景
    1. 其实在使用 docker [container] run 的时候, 我们已经在使用 volume 了
  3. volume
    1. 概述
      1. 类似
        1. linux 里的 卷
        2. windows 里的 盘
    2. 作用
      1. 对接其他设备
      2. 拓展存储空间
      3. 隔离存储区域
      4. 对数据的迁移, 复用, 也有支持

1. 首先, 这个不是 volume

  1. 概述
    1. docker run -v 中, 本地目录 与 容器路径 对接, 不是 volume
  2. 命令

    > docker run --name some-Nginx1 -v $(pwd)/html:/usr/share/Nginx/html -d Nginx
  3. 结果
    1. 容器成功启动
    2. 容器的 '/usr/share/Nginx/html' 目录, 与 宿主机 的 '$(pwd)/html' 目录, 成功关联
    3. 但是
      1. 并没有创建 volume
  4. 验证
    1. docker container inspect
      1. HostConfig 下
        1. Volumes 字段, 值为 null
    2. docker volume ls
      1. 无法查到 新的 volume
  5. 特性
    1. 触发
      1. 填写路径时, 需要用以下方式触发
        1. /
        2. ~/
    2. 路径
      1. host 上如果不存在, 主动创建
      2. container 上如果不存在, 主动创建
    3. 覆盖
      1. 如果冲突, 则以 host 为准

2. 然后, 我们开始使用 volume

  1. 概述
    1. 在 docker run 中使用 volume
  2. 位置
    1. 路径

      # 默认位置
      /var/lib/docker/volumes
      # 具体位置, 可以通过 docker container inspect 查看
  3. 命令

    > docker run --name some-Nginx2 -v html:/usr/share/Nginx/html -d Nginx
  4. 结果
    1. 容器启动成功
    2. 在 volume 的默认路径下, 创建了一个 volume
      1. 名为 html
    3. html 与 容器的路径 绑定成功
  5. 验证
    1. docker volume ls
      1. 可以查看到新的 volume
  6. 其他
    1. volume 名称
      1. 如果不指定, 会随机生成

        > docker run --name some-Nginx2 -v /usr/share/Nginx/html -d Nginx
    2. volume 权限
      1. 权限
        1. 只读
        2. 读写
      2. 指定

        # 默认为 rw
        -v html:/usr/share/Nginx/html[:ro|:rw]

3. volumes-from

  1. 概述
    1. 创建新容器时, 使用和另一个容器相同的挂载策略
  2. 场景
    1. 容器 d1
      1. 有自己的卷
    2. 容器 d2
      1. 继承 d1 的卷
  3. 命令
    1. d1
    2. d2

      > docker container run --name d2 --volumes-from d1 -d Nginx
  4. 埋个坑
    1. 参考里创建 d1 的时候, 没有带 -v
      1. 创建 d2 也没问题
      2. docker container inspect 查看时, 也能正确查看到
      3. 但是这个继承, 到底有没有意义
        1. 还是说, 容器起来的时候, 临时读写层, 也被视为了 volume?
    2. volume 的生命周期
      1. 例子里说了这么个情况
        1. d1 创建, 有了 volume v1
        2. d2 volumes-from 了 d1, 使用了 同样的 v1
        3. d1 关闭了, volume 不受影响
        4. d2 关闭, 没有容器使用 v1,
        5. 然后 v1 的生命周期结束了
      2. 疑问
        1. 什么是 volume 的生命周期
        2. 我试过所有容器都结束, 甚至删掉的情况
          1. -v 创建的卷, 依然存在
          2. 那结束, 又是怎么个回事

2. docker volume

1. 概述

  1. docker volume 命令
    1. 有了上面的认识, 后续的理解, 会方便很多

2. 命令们

  1. ls
    1. 概述
      1. 查看卷列表
    2. 命令

      # 返回 driver 信息 和 volume 的名称
      > docker volume ls
  2. inspect
    1. 概述
      1. 查看卷详情
    2. 命令

      # 稍微详细的信息, 不细说了
      > docker volume inspect <volumeName>
  3. create
    1. 概述
      1. 创建卷
    2. 命令

      # 在默认位置, 创建一个名为 volumeName 的卷
      # 卷 不能重名
      # 创建完之后, 可以用 volumeName 在 创建容器时挂载
      > docker volume crreate <volumeName>
  4. rm
    1. 概述
      1. 删除卷
    2. 命令

      # 删除卷
      > docker volume rm <volumeName> 
  5. prune
    1. 概述
      1. 删除 闲置卷
    2. 命令

      # 删除没有挂载的卷
      > docker volume prune

ps

  1. ref
    1. docker 容器与容器云
      1. 问题
        1. 这本书没把 bind 和 volume 区分得很开
    2. Docker学习笔记(6)——Docker Volume
      1. advantage
        1. 区分了 bind mount 和 volume
      2. disadvantage
        1. 没有 ref 作为支持
    3. docker 入门 —— docker容器数据卷volumes-from
  2. 问题1: 是否有 mount 之类的命令
    1. 条件
      1. 运行之中
  3. 问题2: 上面提到的一些问题
    1. 概述
      1. 需要验证

docker -v 和Dockerfile 中VOLUME 区别

docker -v 和Dockerfile 中VOLUME 区别

在学习Dockerfile的过程中有个VOLUME命令,很多教程或书中说的是用来定义匿名卷的,其作用如下:
  容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

这令我们想起docker的run命令中的 "-v"参数的作用

# docker run --help | grep volume
  -v, --volume list                    Bind mount a volume
      --volume-driver string           Optional volume driver for the container
      --volumes-from list              Mount volumes from the specified

那么Dockerfile中的VOLUME指令实际使用中是不是就是跟docker run中的-v参数一样是将宿主机的一个目录绑定到容器中的目录以达到共享目录的作用呢?
并不然,其实VOLUME指令只是起到了声明了容器中的目录作为匿名卷,但是并没有将匿名卷绑定到宿主机指定目录的功能。
但是当我们生成镜像的Dockerfile中以Volume声明了匿名卷,并且我们以这个镜像run了一个容器的时候,docker会在安装目录下的指定目录下面生成一个目录来绑定容器的匿名卷(这个指定目录不同版本的docker会有所不同)。如我使用的版本如下:

# docker --version
Docker version 18.09.0, build 4d60db4    //docker版本
# pwd
/var/lib/docker/volumes          //默认绑定容器的匿名卷的目录
# ll
total 32
drwxr-xr-x. 3 root root  4096 Nov 25 20:18 593fda6d7b8296bfca22894b326727c734133eebb11c9bc2c25a73b892157a37  //其中一个容器的共享目录文件夹
drwxr-xr-x. 3 root root  4096 Nov 25 20:14 78d890eeb15ac6295484d5e84e97928e981b01501fa40bac40b965fc9e54899a  //其中一个容器的共享目录文件夹
-rw-------. 1 root root 32768 Nov 25 20:18 Metadata.db

就是说当Dockerfile中声明了匿名卷,但是run的时候没有使用-v绑定匿名卷的话,那么docker就会在/var/lib/docker/volumes这个目录下创建一个目录来绑定匿名卷。
所以真正使用的时候我们在Dockerfile构建镜像的时候如:

FROM centos:latest
RUN groupadd -r redis && useradd  -r -g redis redis
RUN yum -y update &&  yum -y install epel-release && yum -y install redis && yum -y install net-tools
RUN mkdir -p /config && chown -R redis:redis /config
VOLUME /share/data      #声明容器中/share/data为匿名卷
EXPOSE 6379

那么使用该Dockerfile构建镜像的为

# docker build -t image-redis    //构建镜像image-redis
......
#docker run -d -it -name redis1 -v /data:/share/data image-redis    //运行一个容器并且将当前机器的/data目录绑定到容器的匿名卷中
.....
#docker run -d -it  -name redis2 image-redis   //运行一个容器但是不绑定目录到容器的匿名卷,这时候再/var/lib/docker/volumes(不同版本目录不一样)中就会创建一个目录绑定匿名卷

Docker 0x06: Docker Volume卷

Docker 0x06: Docker Volume卷

目录

  • Docker Volume卷
    • 一句话什么是docker volume?
    • docker volume特性
    • docker 挂载卷
    • docker 多容器间共享数据券
    • 删除,查看数据卷
    • 备份还原数据卷
    • 小结

Docker Volume卷

在容器技术介绍篇,我们提到过容器的难点在构建网络和文件存储。容器的文件系统虽然可以保存数据,但是容器中的,容器本身是不可迁移的,只能导出其中的文件系统,但是导出文件系统不是迁移容器的最佳实践,最佳实践是镜像。但是镜像是静态数据。改变容器文件系统的东西是不会影响到镜像的。所以就有了挂在volume实践。在build应用镜像的时候,就通过VOLUME给容器创建挂载点,可以挂在宿主机的卷或者其它容器的卷。至此,我们知道了为什么要有volume,因为要持久化容器产生的数据。那本文将说明docker volume是什么,怎么使用挂载,容器间共享同步,迁移备份还原数据。

一句话什么是docker volume?

docker volume是docker容器对应使用的外界存储。

docker volume特性

  1. 如果镜像的挂载点有数据,那么会通过copY ON WRITE技术写道数据卷里。也就是被挂在后数据将显示被挂载的卷的数据,取消挂在后,原挂载点的数据会出现。
  2. 容器读取volume中的数据和宿主机操作数据是同步的,立马生效。
  3. 数据券是可以共享和重用的,多个容器可以使用同一个数据券。类似多主机间NFS共享。
  4. 从以上可以得到另一个特性,容器,数据券,镜像能相互独立存在。
  5. 容器删除,对应的挂在券数据不会丢失。
  6. 容器操作数据券的IO性能,就是具体数据券所在硬件设备的IO性能。

docker 挂载卷

  1. 数据券是外界的,一般就是宿主机文件系统中的一个目录。
  2. 可以在docker 层面创建一个券引用名,通过该引用名可以挂在到容器的挂在点上。当然也可以直接使用文件系统存在目录作为数据券来挂载。
  3. 挂在点也是可以预先在dockerfile中通过VOLUME创建。在启动时会自动在/var/lib/docker/volumes/下随机创建一个券目录,作为挂载点对应的数据券。
  4. 当然,也可以docker volume create v_name 或者dockerfile中 VOLUME 挂载点都没有操作。直接在docker run -v 券:挂载点 ,在从镜像启动容器时,直接设置容器外和容器内目录的挂载。

docker 多容器间共享数据券

要实现这个,不是通过每个容器都挂载相同的物理数据券来实现,而是通过第一个容器挂载数据券后。后面的容器在docker run时,指定一个--volumes-from 第一个dockerid,这样新建的容器就会同第一个容器一样,有相同挂载点对应数据卷。我们通常称第一个容器是“数据卷容器”

删除,查看数据卷

  1. 常看:docker volume ls 列出所有通过docker volume create的卷;docker volume inspect vol_id 常看券详情。
  2. 删除:docker volume rm vol_id

备份还原数据卷

应用产生的数据是非常重要的,数据持久化到数据卷后,持久化数据的备份和迁移还原也是数据卷使用的重要操作。

  1. 备份volume
    备份一个容器的volume,通过启动一个新容器,共享要备份的目标容器,在新容器新挂在备份的目录在新容器的另一个挂载点;由于新容器同时共享了目标容器的volume,所以在新容器中执行tar 共享挂载点数据 放到新挂载点,同时启动新容器时指定--rm,这样就可以在新容器的新挂载点对应的数据卷中找到备份的数据了。
    命令如下:已经知道存在docker容器docker1 其有一个数据卷要备份时/data
    docker run -it --volumes-from docker1 -v /tmp/backup/:/backup --name docker_bk --rm ubuntu tar cvf /backup/docker1.tar /data
    执行成功的话,会炸/tmp/backup/下看到docker1.tar
    这种方式是最专业和正确的操作。

  2. 还原volume
    恢复基本原理一样,也是将新容器启动后,作为数据卷容器,然后再启动第二个容器,挂载备份数目录,并--volumes-from 第一个容器,执行tar xvf 数据到第一个容器的卷中。

    docker run -it --name docker_recover -v test_vol:/data ubuntu /bin/bash
    docker run --rm --volumes-from docker_recover -v /tmp/backup/:/backup ubuntu tar xvf /backup/docker1.tar -C /data

小结

  1. 数据卷的挂载
  2. 容器间共享数据卷和数据卷容器
  3. 利用数据卷容器思想,备份和恢复目标容器的目标数据卷

我们今天的关于用一个实际例子理解 Docker volume 工作原理docker的volume是什么用的分享就到这里,谢谢您的阅读,如果想了解更多关于Docker - 命令 - docker volume、Docker - 命令 - volume 相关、docker -v 和Dockerfile 中VOLUME 区别、Docker 0x06: Docker Volume卷的相关信息,可以在本站进行搜索。

本文标签: