Docker的数据管理


用户在使用 Docker 的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据的共享,这必然涉及容器的数据管理操作。容器中管理数据主要有两种方式:数据卷(Data Volumes),数据卷容器(Data Volume Containers)。

一、数据卷

1. 什么是数据卷:
  • 数据集是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问
  • 数据卷设计的目的,在于数据的持久化,它完全独立于容器的生存周期,因此,Docker不会在容器删除时删除其挂载的数据卷,也不会存在类似的垃圾回收机制,对容器引用的数据卷进行处理。
    Docker的数据管理
    根据上图docker数据卷的结构可知:
  1. docker数据卷是独立于docker的存在,它存在于宿主机中,因此,它与docker容器的生存周期是分离的
  2. docker数据卷可以是目录,也可以是文件
  3. docker容器可利用数据集技术与宿主机实现数据共享
  4. 同一个目录或文件可以支持多个容器的访问,这样实际上实现了容器间数据的共享和交换
2. 数据卷的特点:
  • 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据集中
  • 数据卷可以在容器之间共享和重用
  • 可以对数据卷的内容直接进行修改
  • 数据卷的变化不会影响镜像的更新
  • 卷会一直存在,即使挂载数据卷的容器已经被删除
3. 使用数据卷的最佳场景:
  • 在多个容器之间共享数据,多个容器可以同时以只读或者读写的方式挂载同一个数据卷,从而共享数据卷中的数据。
  • 当宿主机不能保证一定存在某个目录或一些固定路径的文件时,使用数据卷可以规避这种限制带来的问题。
  • 当你想把容器中的数据存储在宿主机之外的地方时,比如远程主机上或云存储上。
  • 当你需要把容器数据在不同的宿主机之间备份、恢复或迁移时,数据卷是很好的选择。
4. 数据卷的使用:
4.1 容器创建时添加数据卷

例如:启动一个Ubuntu容器,并添加一个数据卷
本机文件系统中的目录:在容器中映射的目录

docker run -v /datavolume:/data -it ubuntu  bash

这样的话,在容器该目录中进行的操作实际上就是对宿主机上相应目录的操作
比如,在容器中的data目录上新建一个文件test,填入相应内容,则在宿主机datavolume目录下也会有相应的变化

4.2 docker volume 子命令

docker 专门提供了 volume 子命令来操作数据卷:

docker volume create <name>       创建数据卷
docker volume inspect <name>      显示数据卷的详细信息 
docker volume ls                  列出所有的数据卷
docker volume prune               删除所有未使用的 volumes,并且有 -f 选项
docker volume rm <name>...        删除一个或多个未使用的 volumes,并且有 -f 选项
4.3 使用 mount 语法挂载数据卷

之前我们使用 --volume(-v) 选项来挂载数据卷,现在 docker 提供了更强大的 --mount 选项来管理数据卷。mount 选项可以通过逗号分隔的多个键值对一次提供多个配置项,因此 mount 选项可以提供比 volume 选项更详细的配置。使用 mount 选项的常用配置如下:

  • type 指定挂载方式,我们这里用到的是 volume,其实还可以有 bind 和 tmpfs。
  • volume-driver 指定挂载数据卷的驱动程序,默认值是 local。
  • source 指定挂载的源,对于一个命名的数据卷,这里应该指定这个数据卷的名称。在使用时可以写 source,也可以简写为 src。
  • destination 指定挂载的数据在容器中的路径。在使用时可以写 destination,也可以简写为 dst 或 target。
#例如:
#创建名为 hello 的数据卷,然后把它挂在到容器中的 /world 目录。
docker volume create hello
docker run -it --mount type=volume,source=hello,target=/world ubuntu /bin/bash

二、数据卷容器

1. 什么是数据卷容器:

命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷容器
Docker的数据管理

2. 使用数据卷容器:
#创建数据卷容器
#这里实际上就是启动了一个普通的容器,并在其中创建一个数据卷挂载到 /data 目录
docker run -it -v /data –name mydata ubuntu

#然后在其他容器中就可以使用 --volumes-from 来挂载 mydata 容器中的数据卷
docker run -it --volumes-from mydata –name mycon1 ubuntu
docker run -it --volumes-from mydata –name mycon2 ubuntu
#此时容器 mycon1 和 mycon2 都挂载同一个数据卷到相同的目录 /data。三个容器任何一个在该目录下写入数据其他容器都能看到。

删除挂载了数据卷的容器时,数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式的使用 docker rm -v 命令来指定同时删除关联的容器。

三、一个简单的实践

docker部署数据库:数据库的存储必须要持久化,不能出现容器一删除,数据库也被删除。这个时候就用到了数据卷

  1. 拉取mysql镜像
    mysql已经出到8版本了,有了比较重大的升级,我们这里使用的是5.7.25的版本
docker pull mysql:5.7.25
  1. 运行容器
docker run -p 3306:3306 --name mysql \
-v /usr/local/docker/mysql/conf:/etc/mysql \
-v /usr/local/docker/mysql/logs:/var/log/mysql \
-v /usr/local/docker/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:5.7.25

命令参数:

  • -p 3306:3306:将宿主机的3306端口映射到容器的3306端口
  • -v /usr/local/docker/mysql/conf:/etc/mysql:将主机当前目录下的 conf 挂载到容器的 /etc/mysql
  • -v /usr/local/docker/mysql/logs:/var/log/mysql:将主机当前目录下的 logs 目录挂载到容器的 /var/log/mysql
  • -v /usr/local/docker/mysql/data:/var/lib/mysql:将主机当前目录下的 data 目录挂载到容器的 /var/lib/mysql
  • -e MYSQL_ROOT_PASSWORD=123456:初始化root用户的密码
  1. 使用Navicat连接并导入数据库
    Docker的数据管理