生产环境中使用Docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。
容器中的管理数据主要有两种方式:
- 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;
- 数据卷容器(Data Volume Containers):使用特定容器维护数据卷
1. 数据卷
数据卷(Data Volumes)是一个可供容器使用的特殊目录,他将主机操作系统目录直接映射进容器,类似于linux中的mount行为。
数据卷可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效与方便;
- 对数据卷内数据的修改会立马生效,无论是容器内还是本地操作;
- 对数据卷的更新不会影响镜像,解耦开应用和数据;
- 卷会一直存在,直到没有容器使用,可以安全的卸载它。
1.1. 创建数据卷
Docker提供了Volume命令来管理数据卷,如下可以快速的在本地创建一个数据卷:
[root@localhost ~]# docker volume create -d local test
test
此时,可以查看创建的数据卷位置:
[root@localhost ~]# ll /var/lib/docker/volumes/
drwx-----x 3 root root 19 Apr 10 10:28 test
除了create子命令外,还支持inspect(查看详细信息)、ls(列出已有数据卷)、prune(清理无用数据卷)、rm(删除数据卷)等:
[root@localhost ~]# docker volume inspect test
[
{
"CreatedAt": "2023-04-10T10:28:59+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/test/_data",
"Name": "test",
"Options": null,
"Scope": "local"
}
]
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local ace894fcf308e3cd172187bca5ac2efab77d7b49319796b41a8fa62256cf367a
local test
[root@localhost ~]# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
[root@localhost ~]# docker volume rm test
test
1.2. 绑定数据卷
除了使用volume子命令来管理数据卷外,还可以在创建容器时将主机本地的任意路径挂载到容器内作为数据卷,这种形式创建的数据卷被称为绑定数据卷。
在用docker [container] run命令时,可以使用--monut 选项来使用数据卷。
--mount选项支持三种类型的数据卷:
- volume:普通数据卷,映射到主机/var/lib/docker/volume路径下;
- eface34150b99bacb22b391dc0b01637045712dddcf799634ff6ce0992c147da
- bind:绑定数据卷,映射到主机指定目录下;
- tmpfs:临时数据卷,只存在于内存中。
挂载数据卷
[root@localhost test]# docker run -itd --name ubuntu --volume test:/data ubuntu:18.04
[root@localhost ~]# docker run -itd -P --name test --mount type=bind,source=/testdata,destination=/opt/testdata centos:latest /bin/bash
95e51a42d9fcd1fb65c65e73d1ca8f5360bc0e35dd17d16af626fbda3ed6a7a9
--mount type=bind:绑定类型。
source=/webapp:主机本地目录。 本地路径必须是绝对路径
source=/webapp:容器目录。 容器路径可以为相对路径
另外还有一种写法
docker -run -it -P --name=test -v /testdata:/opt/testdata centos:latest /bin/bash
-v标记可以在容器中中创建一个数据卷
Docker挂载数据卷的默认权限为读写(rw),可以通过ro指定只读:
docker -run -itd -P --name=test -v /testdata:/opt/testdata:ro centos:latest /bin/bash
加了ro之后,容器内对所挂载数据卷内的数据进行修改了。
如果直接挂载文件到容器,可能会导致报错,所以推荐挂载文件锁在的目录到容器内。
2. 数据卷容器
如果需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门提供数据卷给其他容器挂载。
创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata:
[root@localhost ~]# docker run -it -v /dbdata --name dbdata ubuntu
root@8de742b0df5b:/# ls
bin boot dbdata dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
然后可以在其他容器中使用--volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器,并从dbdata容器挂载数据卷:
[root@localhost ~]# docker run -it --volumes-from dbdata --name db1 ubuntu
root@76245b9817d7:/# ls
bin boot dbdata dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
[root@localhost ~]# docker run -it --volumes-from dbdata --name db2 ubuntu
root@6b9b4283b624:/# ls
bin boot dbdata dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
此时db1和db2都挂载同一个数据卷到相同的/dbdata目录,三个容器任何一方在该目录下的写入,其他容器都能看到。
例如:
在db2创建一个目录
root@6b9b4283b624:/dbdata# mkdir db2test
root@6b9b4283b624:/dbdata# ls
db2test
在db1中能看到
[root@localhost ~]# docker exec -it db1 /bin/bash
root@76245b9817d7:/# cd dbdata/
root@76245b9817d7:/dbdata# ls
db2test
可以多次使用--volumes-from参数从多个容器挂载多个数据卷,还可以从其他已经挂载了容器卷的容器来挂载数据卷:
[root@localhost ~]# docker run -itd --name db3 --volumes-from db1 ubuntu
8681e5d0c2565f6dd8bf30190078ce268320ba02b3ec28403dbceeeed3aa9c2f
[root@localhost ~]# docker exec -it db3 /bin/bash
root@8681e5d0c256:/# cd /dbdata/
root@8681e5d0c256:/dbdata# ls
db1test db2test
使用--volumes-from 参数所挂载的数据卷的容器本身并不需要保持在运行状态。
3. 利用数据卷容器来迁移数据
可以利用数据卷容器对其中的数据卷进行备份、恢复,以实现数据的迁移。
3.1. 备份
[root@localhost /]# docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata
tar: Removing leading `/' from member names
/dbdata/
/dbdata/db2test/
/dbdata/db1test/
[root@localhost /]# ls
backup.tar
命令分析:
首先利用ubuntu镜像创建一个名为worker的容器。使用--volumes-from参数来让worker容器挂载dbdata容器的数据卷,使用-v $(pwd):/backup参数来挂载主机本地的当前目录到worker容器的/backup目录。
worker容器启动后,使用tar cvf /backup/backup.tar /dbdata命令将/dbdata下内容备份为容器内的 /backup/backup.tar,即主机当前目录下的backup.tar。
3.2. 恢复
恢复数据到一个容器:
首先创建一个带有数据卷的容器dbdata2:
[root@localhost /]# docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
然后创建一个新的容器,挂载dbdata2的容器,并使用untar解压备份文件到所挂载的容器中:
[root@localhost /]# docker run -it -v /dbdata --name dbdata2 ubuntu /bin/bash
然后再创建一个新的容器,挂载dbdata2的容器,并使用untar解压备份文件到所挂载的容器卷中:
[root@localhost /]# docker run --volumes-from dbdata2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar
dbdata/
dbdata/db2test/
dbdata/db1test/
[root@localhost /]# docker exec -it dbdata2 /bin/bash
root@3440cb89d33b:/# ls
bin boot dbdata dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
root@3440cb89d33b:/# cd dbdata/
root@3440cb89d33b:/dbdata# ls
db1test db2test