06_Docker数据卷(Volume)

参考资料

  • 《docker volume》
  • 《docker容器的数据卷以及使用方式》

Docker容器默认把数据存储到容器内部,当容器删除的时候,容器内的数据会同步删除。

很多情况下,我们是不希望数据被删除的,常规的有2种方式能达到目的:

  1. 在删除容器之前将数据拷贝到本地。
  2. 通过数据卷把宿主机文件夹映射到容器内部,这就是数据卷。

Docker数据卷种类和特点

Docker数据卷(Volume)有两种:

  • 数据卷
  • 数据卷容器

数据卷是特殊设计的目录,独立在容器的生命周期外,可以绕过联合文件系统(UnionFS),可以为一个或多个容器提供服务。

Docker数据卷的特点:

  • 可以在容器和宿主机之间或容器与容器之间共享和重用;
  • 在容器和宿主机之间双向同步;
  • 数据卷大小不会附加到容器上;
  • 数据卷的变化,不会影响镜像的更新;
  • 会一直存在,直到没有任何容器使用它,才能使用命令docker volume rm [volumes名字]删除。

数据卷大小不会附加到容器上,这就类似软链接。可以启动两个Tomcat,并把其中一个Tomcat的logs目录挂载进去,分别通过docker export导出,发现挂载logs目录的导出文件中logs目录没文件,未挂载logs目录的,导出文件中有文件。

Docker数据卷

挂载

Docker使用-v指令挂载数据卷,挂载多个时,使用多个-v指令。

Docker数据卷挂载常规的有3种方式:

  • 指定目录挂载
  • 匿名挂载
  • 具名挂载

指定目录挂载

在挂载数据卷时,指定宿主机目录:容器目录。Docker不会自动在安装目录下创建数据卷。

  • 语法
# -v 为挂载目录选项
docker run -v 宿主机目录:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
  • 示例
# 启动tomcat,并给tomcat挂载日志目录
# -d 后台运行
# --name tomcat 指定别名
# -P 随机指定端口,启动后可通过docker ps命令查看映射的端口
# -v 宿主机目录:容器目录 挂载目录到容器
docker run -d --name tomcat -P -v /home/docker/volumes/tomcat/logs:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

注意:指定目录挂载,不能使用./相对路径,可以使用~/相对路径。

  • ./ 表示当前路径下的目录;
  • ~/ 表示用户主目录,也就是登录系统后直接进入的目录。
  • 分析

Tomcat启动后,就可以在/home/docker/volumes/tomcat/logs目录中看到有日志文件生成。

进入容器,也能看到日志文件,说明挂载成功。

# 进入容器内部
# -it 交互模型运行
# /bin/bash 以/bin/bash交互
docker exec -it tomcat /bin/bash

此时在宿主机或容器中修改文件,另外一边都能看到,说明是双向同步的。

使用docker inspect查看容器元数据,在Mounts节点下可以看到挂载的数据卷。

# 查看容器元数据


# 输出
...
"Mounts": [
      {
           "Type": "bind",
           "Source": "/home/docker/volumes/tomcat/logs",
           "Destination": "/usr/local/tomcat/logs",
           "Mode": "",
           "RW": true,
           "Propagation": "rprivate"
      }
],
...

使用docker volume ls命令查看Docker所有挂载的数据卷,发现并没有找到这个挂载的数据卷。说明指定目录挂载方式并不会把数据卷信息存储到Docker中,也就是并不能通过具名或匿名挂载方式复用该数据卷。

# 查看所有挂载的数据卷
docker volume ls

# 输出
DRIVER              VOLUME NAME
local               0ea11ee5a377263e6a62a61afdd554f12f3f61e0e69fb603794363637668f270
local               28ad647f7dc23b3a04c96f8ba8eeca08c0766a1b2669bc42162e43ddcd585164
local               85a5ba99cf1ca1a52e745685bede94be81f6d79e44ef108192d2d27817460331

要想多个Tomcat共用这个数据卷,那么就只能重新输入完整的宿主机文件路径来挂载。

# 复用数据卷
# -v 后面跟的是完整的宿主机文件路径:容器目录
docker run -d --name tomcat1 -P -v /home/docker/volumes/tomcat/logs:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

匿名挂载

在挂载数据卷时,只指定容器内部的目录。Docker会自动将数据卷用一串很长的字符命名。

  • 语法
docker run -v 容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
  • 示例
# 启动tomcat,并给tomcat挂载日志目录
# -v后只指定容器内部目录
docker run -d --name tomcat -P -v /usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
  • 分析

使用docker volume ls命令查看,发现多了一个数据卷,数据卷名称是一串很长的字符。

# 查看所有数据卷
docker volume ls

# 输出
DRIVER              VOLUME NAME
local               0ea11ee5a377263e6a62a61afdd554f12f3f61e0e69fb603794363637668f270
local               2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4
local               28ad647f7dc23b3a04c96f8ba8eeca08c0766a1b2669bc42162e43ddcd585164
local               85a5ba99cf1ca1a52e745685bede94be81f6d79e44ef108192d2d27817460331

使用docker volume inspect 数据卷ID命令查看数据卷详情,发现数据卷在Docker目录下。

# 查看数据卷元数据
docker volume inspect 2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4

# 输出
[
    {
        "CreatedAt": "2020-08-07T12:05:52+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4/_data",
        "Name": "2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4",
        "Options": null,
        "Scope": "local"
    }
]

使用ls命令查看目录内容,发现里面有Tomcat的日志文件,说明挂载成功了。

# 查看目录内容
ls /var/lib/docker/volumes/2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4/_data

# 输出
catalina.2020-08-07.log  host-manager.2020-08-07.log  localhost.2020-08-07.log  localhost_access_log.2020-08-07.txt  manager.2020-08-07.log

使用docker volume rm 数据卷ID 删除,发现删不掉。

# 删除数据卷
docker volume rm 2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4

停止并删除容器后,发现可以删除成功,说明,只要数据卷还在被使用(或引用)就不能删除

具名挂载

在挂载数据卷时,指定数据卷名称:容器内部的目录。Docker会按照指定的数据卷名称命名。

语法

docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
# 或
docker volume create 数据卷名称
docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]

示例

# 启动tomcat,并给tomcat挂载日志目录
# -v后指定数据卷名称:容器内部目录
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

具名挂载和指定目录挂载对比

  • 具名挂载:

    • 数据卷命名规则:[a-zA-Z0-9][a-zA-Z0-9_.-],只能以字母或数据开头,不能包含/~/
    • 具名挂载会在Docker目录下生成自定义名称的数据卷,可以使用docker volume ls查看。
  • 指定目录挂载:

    • 数据卷是一个完整的路径,也就是以/~/开头的。
    • 指定目录挂载不会在Docker目录下生成数据卷。

挂载方式对比

挂载方式 生成数据卷 命名规则 默认名称
指定目录挂载 × - -
匿名挂载 - 随机字符串
具名挂载 [a-zA-Z0-9][a-zA-Z0-9_.-] 指定的名称

Docker数据卷容器

如果一个非常复杂的容器,需要挂载很多个数据卷。如果这个容器要同时启动多个,一个个输入很长的挂载命令很容易出错。或者多个容器之间需要共享数据,此时就推荐使用数据卷容器了。

数据卷容器

数据卷容器就是挂载了数据卷的容器,数据卷容器可以被别的容器挂载。

数据卷容器的出现是为了解决容器之间数据共享问题。

数据卷容器的优势:

  • 可以被多个容器简单的复用;
  • 与数据卷容器是否启动无关。

数据卷容器使用

  • 语法
docker run --volumes-from 数据卷容器 [OPTIONS] IMAGE [COMMAND] [ARG...]
  • 示例

首先根据上面的示例,准备一个数据卷容器。

# 创建一个tomcat容器,并挂载数据卷
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

使用--volumes-from 数据卷容器指令挂载这个数据卷容器。

# 启动tomcat,并给tomcat挂载数据卷容器
# 使用--volumes-from,挂载数据卷容器
docker run -d --name tomcat_link -P --volumes-from tomcat tomcat:8.5.57-jdk8-openjdk

挂载多个数据卷容器时,使用多个--volumes-from 数据卷容器指令挂载。

然后停用tomcat容器,tomcat_link容器还是能正常使用数据卷,说明数据卷容器是否启动,对使用者来说不影响。

命令集

挂载

指定目录挂载

  • 语法
# -v 为挂载目录选项
docker run -v 宿主机目录:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
  • 示例
# 启动tomcat,并给tomcat挂载日志目录
# -d 后台运行
# --name tomcat 指定别名
# -P 随机指定端口,启动后可通过docker ps命令查看映射的端口
# -v 宿主机目录:容器目录 挂载目录到容器
docker run -d --name tomcat -P -v /home/docker/volumes/tomcat/logs:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

匿名挂载

  • 语法
docker run -v 容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
  • 示例
# 启动tomcat,并给tomcat挂载日志目录
# -v后只指定容器内部目录
docker run -d --name tomcat -P -v /usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

具名挂载

  • 语法
docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
# 或
docker volume create 数据卷名称
docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
  • 示例
# 启动tomcat,并给tomcat挂载日志目录
# -v后指定数据卷名称:容器内部目录
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

数据卷容器挂载

  • 语法
docker run --volumes-from 数据卷容器 [OPTIONS] IMAGE [COMMAND] [ARG...]
  • 示例
# 创建一个tomcat容器,并挂载数据卷
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk

# 启动tomcat,并给tomcat挂载数据卷容器
# 使用--volumes-from,挂载数据卷容器
docker run -d --name tomcat_link -P --volumes-from tomcat tomcat:8.5.57-jdk8-openjdk

说明:被挂载的Tomcat容器为正常的数据卷容器。

数据卷操作

创建数据卷:docker volume create

  • 语法
docker volume create [OPTIONS] [VOLUME]
  • 示例
# 创建一个匿名数据卷
docker volume create

# 创建一个testvolume数据卷
docker volume create testvolume

查看所有数据卷:docker volume ls

  • 语法
docker volume ls [OPTIONS]
  • 示例
# 查看所有数据卷
docker volume ls

查看指定数据卷元数据:docker volume inspect

  • 语法
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
  • 示例
# 查看testvolume数据卷元数据
docker volume inspect testvolume

删除数据卷:docker volume rm/prune

  • 语法
# 删除一个或多个数据卷
docker volume rm [OPTIONS] VOLUME [VOLUME...]

# 删除所有未使用的数据卷
docker volume prune [OPTIONS]
  • 示例
# 删除testvolume数据卷
docker volume rm testvolume

# 删除所有未使用的数据卷
docker volume prune

你可能感兴趣的:(06_Docker数据卷(Volume))