在生产环境中使用 Docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。

容器中的管理数据主要有两种方式:

  • 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;
  • 数据卷容器(Data Volume Containers):使用特定容器维护数据卷。

本节将首先介绍如何在容器内创建数据卷,并且把本地的目录或文件挂载到容器内的数据卷中。接下来,介绍如何使用数据卷容器在容器和主机、容器和容器之间共享数据,并实现数据的备份和恢复。

数据卷

数据卷(Data Volumes)是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount行为。

数据卷可以提供很多有用的特性:

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 数据卷默认会一直存在,即使容器被删除

创建数据卷

如下命令可以快速在本地主机创建一个数据卷 test:

  1. > docker volume create -d local test

创建完的数据卷,可在本地的 /var/lib/docker/volumes 路径下查看。

  1. > ls -l /var/lib/docker/volumes

image.png

绑定数据卷

除了单独创建数据卷之外,还可以通过创建容器时将本机的任意路径挂载到容器内作为数据卷,这种数据卷称为绑定数据卷。

在 docker run 时,可以通过选项 --mount 来使用数据卷,它支持三种类型的数据卷,包括:

  • volume:普通数据卷,映射到主机 /var/lib/docker/volumes 路径下;
  • bind:绑定数据卷,映射到主机指定路径下;
  • tmpfs:临时数据卷,只存在于内存中。

下面看一个例子。

  1. > mkdir -p /tmp/docker-test/webapp
  2. # 创建一个容器,并创建一个数据卷挂载到容器下的 /usr/share/nginx/html 目录下
  3. > docker run -d --name nginx-test --mount type=bind,source=/tmp/docker-test/webapp,destination=/usr/share/nginx/html hub.c.163.com/library/nginx:latest
  4. # 如果使用旧命令
  5. > docker run -d --name nginx-test -v /tmp/docker-test/webapp:/usr/share/nginx/html hub.c.163.com/library/nginx:latest

image.png

这个功能的好处是用户可以放置一些程序或数据到本地目录中实时进行更新,然后在容器内运行和使用。

:::warning 注意:

  • —mount 的值之间不能有空格,指定的本地目录必须先创建,本地目录的路径必须是绝对路径;
  • 容器内路径可以为相对路径,如果目录不存在,Docker 会自动创建。 :::

Docker 挂载主机目录的默认权限是读写(rw),用户也可以通过增加 readonly 指定为只读:

  1. > > docker run -d --name nginx-test --mount type=bind,source=/tmp/docker-test/webapp,destination=/usr/share/nginx/html,readonly hub.c.163.com/library/nginx:latest

加了 readonly 之后,在容器内对所挂载数据卷(本机目录)内的操作(增删改)则会报错。

查看数据卷

查看数据卷的具体信息可以使用以下命令:

  1. > docker inspect test

image.png

删除数据卷

删除数据卷的命令如下:

  1. > docker volume rm test

数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker container rm -v test [CONTAINER ID]这个命令。

无主的数据卷可能会占据很多空间,要清理请使用以下命令:

  1. > docker volume prune

数据卷容器

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门提供数据卷给其他容器挂载

首先创建一个数据卷容器 dbdata,并在其中创建一个数据卷挂载到容器的 /tmp/dbdata:

  1. > docker run -dit -v /tmp/dbdata --name dbdata ubuntu

查看 /tmp/dbdata 目录:

  1. root@47957f5f8b48:/# ls /tmp/dbdata

然后,可以在其他容器中使用 --volumes-from 来挂载 dbdata 容器中的数据卷,例如创建 db1 和 db2 两个容器,并从 dbdata 容器挂载数据卷:

  1. > docker run -it --name db1 --volumes-from dbdata ubuntu
  2. > docker run -it --name db2 --volumes-from dbdata ubuntu

此时,容器 db1 和 db2 都将挂载同一个数据卷到相同的目录 /tmp/dbdata,三个容器任何一方在该目录下的写入,其他容器都可以看到。

例如,在 dbdata 容器中创建一个 test 文件:

  1. # dbdata容器
  2. root@47957f5f8b48:/# cd /tmp/dbdata
  3. root@47957f5f8b48:/# touch test.txt
  4. root@47957f5f8b48:/# ls

在 db1 容器内查看 test.txt:

  1. # db1容器
  2. root@44f43b4b9867:/# ls /tmp/dbdata

image.png

同时,还可以多次使用 --volumes-from 参数来从多个容器挂载多个数据卷,还可以从其他已经挂载了容器卷的容器来挂载数据卷(db1):

  1. > docker run -it --name db3 --volumes-from dbdata db1

:::info 使用 —volumes-from 参数所挂载数据卷的容器自身并不需要保持在运行状态。 :::

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

使用数据卷容器可以让用户在容器之间自由地升级和移动数据卷。

利用数据卷容器来迁移数据

可以利用数据卷容器对其中的数据卷进行备份、恢复,以实现数据的迁移。

备份

备份数据卷的步骤如下:

  1. # 1. 创建一个数据卷容器web1,-v指定数据卷名为web,并挂载到容器web1的/tmp/web目录下,-d指定后台运行
  2. > docker run -dit --name web1 -v web:/tmp/web ubuntu:18.04
  3. # 2. 查看容器和数据卷是否创建成功
  4. > docker ps
  5. > docker volume ls
  6. # 3. 在/tmp/web下创建一个目录test和一个文件test.txt,查看是否创建成功
  7. > docker exec -it web1 mkdir /tmp/web/test
  8. > docker exec -it web1 touch /tmp/web/test.txt
  9. > docker exec -it web1 ls /tmp/web
  10. # 4. 备份
  11. # 创建名称为backup的临时容器,--volumes-from指定挂载数据卷容器web1的共享数据卷/tmp/web,-v参数指定将本机的目录/tmp/docker-test挂载到临时容器的/tmp/backup目录,执行压缩将临时容器的/tmp/web目录打包压缩成/tmp/backup目录下名为web.tar的备份文件
  12. > docker run -it --name backup --volumes-from web1 -v /tmp/docker-test:/tmp/backup ubuntu:18.04 tar cvf /tmp/backup/web.tar /tmp/web
  13. # 5. 因为本机的目录/tmp/docker-test挂载到临时容器的/tmp/backup目录,所以打包出来的文件可以在本机中查看
  14. > ls /tmp/docker-test

image.png

恢复

恢复数据卷的步骤如下:

  1. # 1. 创建一个空数据卷容器webback用来存放解压出来的备份文件,-v指定数据卷名为webdata,并挂载到容器webback的/tmp/web目录下,-d指定后台运行
  2. > docker run -dit --name webback -v webdata:/tmp/web ubuntu:18.04
  3. # 2. 查看创建的容器和数据卷
  4. > docker ps
  5. > docker volume ls
  6. # 3. 解压
  7. # 创建一个临时的容器recover,--volumes-from指定挂载数据卷容器webdata的共享数据卷/tmp/web,-v参数指定将本机的目录/tmp/docker-test挂载到临时容器的/tmp/backup目录,执行恢复命令将临时容器的/tmp/web目录下的web.tar解压到webback容器的数据卷/tmp/web中
  8. > docker run -it --name recover --volumes-from webback -v /tmp/docker-test:/tmp/backup ubuntu:18.04 tar xvf /tmp/backup/web.tar
  9. # 4. 查看webback容器中是否存在解压的文件,结果与web1中的压缩的文件相同
  10. > docker exec -it webback ls /tmp/web
  11. > docker exec -it web1 ls /tmp/web

image.png

为了验证 web1 数据卷备份恢复到 webdata 数据卷的数据,再启动一个新容器挂载 webdata 数据卷查看数据。

  1. > docker run -dit --name webtest -v webdata:/tmp/web ubuntu:18.04
  2. > docker ps
  3. > docker exec -it webtest ls /tmp/web

image.png

to be continue…