我们在使用 docker 的时候会将一些数据(例如网站文件、配置文件、数据库文件等)存储在容器中。这样存在一个严重的问题,如果容器出现损坏(例如无法启动,被删除等)那么存储在容器中的数据就会丢失,即使我们进行了容器备份,数据也不可能恢复到故障发生时。如果要解决这个问题,我们就需要用到 docker 的数据管理。在 docker 中数据管理一共有两种方式,分别是数据卷和数据卷容器,下面我们来一一讲解。
零、数据卷
数据卷是一个可供容器使用的特殊目录,将宿主机的目录直接映射进容器。使用数据卷有如下几点好处:
- 多个容器可以使用同一个数据卷,方便容器间高效的传递数据;
- 不管是在容器内操作还是宿主机上操作,对数据卷内数据的修改会立马生效;
- 解耦了应用和数据,更新数据卷不会影响容器的运行;
- 数据卷一直存在,即使使用它的容器被销毁,它依然存在。
1.创建数据卷
使用 volume 可以管理数据卷,下面我们用这命令来创建一个数据卷:
docker volume create -d local myVolume
执行完上述命令后,/var/lib/docker/volumes 下面将会出现一个名字是 myVolume 的目录,这个目录就是我们创建的数据卷。
如果需要查看数据卷的信息,可以使用 inspect 命令:
docker volume inspect myVolume
上述命令将会返回 myVolume 数据卷的详细信息。
同样,我们可以使用 ls 命令来查看已经存在的数据卷:
docker volume ls
当我们删除数据卷时可以使用 rm 命令:
docker volume rm myVolume
注意:如果要删除数据卷,必须解除容器对数据卷的绑定。
若存在多个无用的数据卷,则可以通过 prune 命令来删除无用的数据卷:
docker volume prune
2.绑定数据卷
我们可以在创建容器的同时将本地任意路径挂载到容器中。docker 为我们提供了 mount 命令了来使用数据卷,该命令支持三种类型的数据卷:
- -volume :普通数据卷,映射在 /var/lib/docker/volumes 目录下;
- -bind :绑定数据卷,映射到宿主机任意位置;
- -tmpfs :临时数据卷,映射到宿主机内存中。
下面我们通过创建一个 Web 容器,来看一下具体怎么在创建容器时绑定数据卷:
docker run -d --name=web --mount type=bind,source=/webapp,destination=/opt/webapp training/webapp python app.py
上述命令将容器中的 /opt/webapp 路径绑定到宿主机的 /webapp 路径上,名例中的 type=bind 意思是将容器中指定的目录映射到宿主机指定的位置。
注意:指定的本地目录的路径必须是绝对路径,但是容器中的路径可以是相对路径。如果目录不存在,Docker 会自动创建。
上述命令还有一个简单的写法:
docker run -d -P --name web -v /webapp:/opt/webapp training/webapp python app.py
这个方法同样也可以到达前面命令的效果。
默认情况下,我们创建容器时绑定的数据卷是可读写的,如果需要将其设置为只读的,我们只需将前面的代码改动如下:
docker run -d -P --name web -v /webapp:/opt/webapp:ro training/webapp python app.py
这里的 :ro 的意思就是将数据卷设置为只读,这样在容器中就无法修改数据卷中的任何内容了。
注意:不可将文件直接挂载到容器中,因为如果直接挂载的文件出现修改的情况,很有可能导致文件的 inode 改变,从而导致 Docker 容器报错。
一、数据卷容器
当有多个容器需要使用多个持续更新的数据卷时,这时使用数据卷容器就很有必要。所谓数据卷容器就是专门提供多个数据卷给其他容器使用的容器。
例如我们需要将 database 目录挂在到容器中,并将这个容器作为数据卷挂载到另一个容器中:
创建数据卷容器,将 database 目录挂载到容器中,并将容器命名为 database
docker run -it -v /database --name database ubuntu
2. 接着我们通过 –volumes-from 命令将数据卷容器挂载到容器 mydb1 和 mydb2
docker run -it --volumes-from database --name mydb1 ubuntu docker run -it --volumes-from database --name mydb2 ubuntu
执行完上述两个步骤后,数据卷容器就挂载到了 mydb1 和 mydb2 容器中了,这时我们如果在这三个容器中的任意一个容器的 database 目录中写入数据,其他两个容器就可以看得到这个写入。
小提示:如果要挂在多个数据容器,只需要使用多个 -volumes-from 参数即可。
注意:如果删除了挂载的数据卷容器,数据卷不会被删除。如果要删除数据卷则需要把所有该数据卷的容器解除挂载后方可删除数据卷。
二、迁移数据
我们可以利用数据卷容器对数据卷进行备份、迁移和恢复。我们来看一下具体该怎么做。
1.备份
首先我们需要创建一个容器 backupDatabase , 然后使用 --volumes-form 参数将 database 数据卷容器挂载到 backupDatabase 容器,接着使用 -v$(pwd):/backup 参数来挂在本地的当前目录到 backupDatabase 容器的 /backup 目录,最后当 backupDatabase 启动后使用 tar 命令将 /database 下的内容备份到容器中的 /backup 目录中,这样我们就可以在宿主机的当前目录下看到备份的文件。按照上述操作,命令如下:
docker run --volumes-from database -v $(pwd):/backup --name backupDatabase ubuntu tar cvf /backup/backup.tar /database
2. 恢复
恢复就相对来说简单了,首先创建一个带有数据卷的容器 hf 然后创建一个新容器 hf2 ,并使用 untar 命令将备份解压到所挂在的容器卷中。我们来看一下具体怎么做:
docker run -v /dbdata --name hf ubuntu /bin/#!/usr/bin/env bash docker run --volumes-from hf2 -v $(pw):/backup busybox tar xvf /backup/backup.tar