文章目录
- 1 数据卷
- 1.1 数据卷基本操作
- 1.1.1 创建并操作数据卷
- 1.1.2 查看指定数据卷的信息
- 1.1.3 列出已有数据卷
- 1.1.4 清理无用数据卷
- 1.1.5 删除数据卷
- 1.2 绑定数据卷
- 1.2.1 挂载普通数据卷
- 新参数-mount
- 旧参数-v
- 1.2.2 绑定数据卷
- 新参数-mount
- 旧参数-v
- 1.2.3 临时数据卷
- 1.2.4 挂载一个本地主机文件作为数据卷
- 2 数据卷容器
- 3 利用数据卷容器来迁移数据
- 3.1 备份
- 3.2 恢复
在生产环境中使用Docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。
容器中的管理数据主要有两种方式 :
- 数据卷 ( Data Volumes ) : 容器内数据直接映射到本地主机环境;
- 数据卷容器( Data Volume Containers ) : 使用特定容器维护数据卷。
docker volume
- bind muount #挂载任意目录或文件
- Volumes #固定路径的目录,docker管理
- tmpfs mounts #存放宿主机内存中
1 数据卷
数据卷( Data Volumes )是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount行为。
数据卷可以提供很多有用的特性 :
- 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效与方便;
- 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
- 对数据卷的更新不会影响镜像,解耦开应用和数据;
- 数据卷会一直存在,直到没有容器使用,可以安全地卸载它;
1.1 数据卷基本操作
1.1.1 创建并操作数据卷
Docker提供了volume
子命令来管理数据卷,如下命令可以快速在本地创建一个数据卷:
(base) pang@pang-HP:~$ sudo docker volume create -d local test
test
(base) pang@pang-HP:~$ sudo docker volume ls
DRIVER VOLUME NAME
local nexus-data
local test
(base) pang@pang-HP:~$
此时 ,查看/var/lib/docker/volumes
路径下,会发现所创建的数据卷位置 :
(base) pang@pang-HP:~$ sudo ls -alrt /var/lib/docker/volumes
总用量 40
drwx-----x 3 root root 4096 6月 17 14:41 nexus-data
drwx--x--- 13 root root 4096 6月 20 08:39 ..
brw------- 1 root root 253, 0 6月 20 08:39 backingFsBlockDev
drwx-----x 3 root root 4096 6月 21 09:49 test
-rw------- 1 root root 32768 6月 21 09:49 metadata.db
drwx-----x 4 root root 4096 6月 21 09:49 .
(base) pang@pang-HP:~$
1.1.2 查看指定数据卷的信息
(base) pang@pang-HP:~$ sudo docker volume inspect test
[
{
"CreatedAt": "2022-06-21T09:49:42+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/test/_data",
"Name": "test",
"Options": {},
"Scope": "local"
}
]
(base) pang@pang-HP:~$
1.1.3 列出已有数据卷
(base) pang@pang-HP:~$ sudo docker volume ls
DRIVER VOLUME NAME
local nexus-data
local test
(base) pang@pang-HP:~$
1.1.4 清理无用数据卷
无主的数据卷可能会占据很多空间,要清理请使用以下命令
(base) pang@pang-HP:~$ sudo 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
Deleted Volumes:
test
Total reclaimed space: 0B
(base) pang@pang-HP:~$
1.1.5 删除数据卷
$ docker volume rm test
数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用docker rm -v
这个命令。
1.2 绑定数据卷
除了使用volume
子命令来管理数据卷外,还可以在创建容器时将主机本地的任意路径挂载到容器内作为数据卷,这种形式创建的数据卷称为绑定数据卷。
在用docker [container] run
命令的时候,可以使用-mount
选项来使用数据卷。其支持三种类型的数据卷,包括 :
-
volume
: 普通数据卷,映射到主机/var/lib/docker/volumes
路径下; -
bind
:绑定数据卷,映射到主机指定路径下; -
tmpfs
:临时数据卷,只存在于内存中 。
1.2.1 挂载普通数据卷
不指定挂载目录,默认目录
/var/lib/docker/volumes/xxx/_data/
docker volumes可管理,官方推荐
新参数-mount
下面使用centos:7
镜像创建一个centos容器,并创建一个数据卷挂载到容器的/vdata
目录:
(base) pang@pang-HP:~$ sudo docker run -d --name centos1 --mount source=test,target=/vdata centos:7 tail -f /dev/null
ff7b847b4b08aef5cf1cb6aa322c252feef4c2118f530a30e7acabbb796c38f8
(base) pang@pang-HP:~$ sudo docker inspect centos1
...
"Mounts": [
{
"Type": "volume",
"Source": "test",
"Target": "/vdata"
}
],
...
"Mounts": [
{
"Type": "volume",
"Name": "test",
"Source": "/var/lib/docker/volumes/test/_data",
"Destination": "/vdata",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
...
(base) pang@pang-HP:~$
旧参数-v
另外,创建容器指令的-v
参数也能来帮忙我们在容器内创建数据卷。例如:在使用docker run
命令的时候,使用-v
标记可以在容器内创建一个数据卷。多次使用-v
标记可以创建多个数据卷。如:
(base) pang@pang-HP:~$ sudo docker run -d --name centos -v /vdata centos:7 tail -f /dev/null
b330d8bf4dfc88ae55a2db5b66e79c0046dac7f0c047ea29296188bcee7b2286
(base) pang@pang-HP:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b330d8bf4dfc centos:7 "tail -f /dev/null" 6 seconds ago Up 6 seconds centos
(base) pang@pang-HP:~$
这种情况下,会在volume默认创建一个volume,名称为一串字符串序号。如下图:50eed726cedc6978b00494dd424就是自动创建的。
(base) pang@pang-HP:~$ sudo docker volume ls
DRIVER VOLUME NAME
local 50eed726cedc6978b00494dd42429ccbb4a23991e472bc777985e71742995168
local nexus-data
(base) pang@pang-HP:
并且在容器中的vdata目录的改动会同步到host的volume中。
(base) pang@pang-HP:~$ sudo docker exec -it centos /bin/bash
[root@b330d8bf4dfc /]# cd /vdata
[root@b330d8bf4dfc vdata]# ll
total 0
[root@b330d8bf4dfc vdata]# touch aaa.txt
[root@b330d8bf4dfc vdata]# exit
exit
(base) pang@pang-HP
通过volume的信息找到host对应目录,并查看变动
(base) pang@pang-HP:~$ sudo docker volume inspect 50eed726cedc6978b00494dd42429ccbb4a23991e472bc777985e71742995168
[
{
"CreatedAt": "2022-06-20T14:58:11+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/50eed726cedc6978b00494dd42429ccbb4a23991e472bc777985e71742995168/_data",
"Name": "50eed726cedc6978b00494dd42429ccbb4a23991e472bc777985e71742995168",
"Options": null,
"Scope": "local"
}
]
(base) pang@pang-HP:~$ sudo ls /var/lib/docker/volumes/50eed726cedc6978b00494dd42429ccbb4a23991e472bc777985e71742995168/_data
aaa.txt
(base) pang@pang-HP:~$
1.2.2 绑定数据卷
为保证Dockerfile可移植,构建镜像不能使用bind muount
绑定数据卷,即挂载一个主机目录作为数据卷,就是指将host的目录与容器目录进行绑定。这个功能在进行应用测试的时候十分方便,比如用户可以放置一些程序或数据到本地目录中实时进行更新,然后在容器内运行和使用。
为了实现这个功能,也是新参数-mount
与旧参数-v
都可以实现。
当进行绑定时,无论是-mount
参数中的source
,还是-v
参数中:
前面的部分,均必须是绝对路径(如果目录不存在,Docker会自动创建)。否则创建容器时会提示错误:
(base) pang@pang-HP:~$ sudo docker run -d --name centos3 --mount type=bind,source=test,target=/vdata centos:7 tail -f /dev/null
docker: Error response from daemon: invalid mount config for type "bind": invalid mount path: 'test' mount path must be absolute.
See 'docker run --help'.
(base) pang@pang-HP:~$ dang
另外,Docker挂载数据卷的默认权限是读写(rw),用户也可以通过,ro指定为只读。如下面指令,加了:ro
之后,容器内挂载的数据卷的数据就无法修改了(注,这里只能是-v
参数才能使用:ro
)。
(base) pang@pang-HP:~$ sudo docker run -d --name centos2 -v /home/pang/vdata:/vdata:ro centos:7 tail -f /dev/null
3aca6d52c1b49e855595a009cc654e550be61eafa1b51c04a826a2373c26d8d9
(base) pang@pang-HP:~$ sudo docker exec -it centos2 /bin/bash
[root@3aca6d52c1b4 /]# cd /vdata
[root@3aca6d52c1b4 vdata]# ls
aaa.txt
[root@3aca6d52c1b4 vdata]# touch bbb.txt
touch: cannot touch 'bbb.txt': Read-only file system
[root@3aca6d52c1b4 vdata]#
新参数-mount
(base) pang@pang-HP:~$ sudo docker run -d --name centos2 --mount type=bind,source=/home/pang/vdata,target=/vdata centos:7 tail -f /dev/null
68e39f878a2956799a5e85cf6ec6896f8eaf7fc85c14d4937e3d1d26325b2255
(base) pang@pang-HP:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
68e39f878a29 centos:7 "tail -f /dev/null" 4 seconds ago Up 4 seconds centos2
ff7b847b4b08 centos:7 "tail -f /dev/null" 52 minutes ago Up 52 minutes centos1
9a102684ab20 sonatype/nexus3 "sh -c ${SONATYPE_DI…" 30 hours ago Up 30 hours 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp, 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp nexus3
(base) pang@pang-HP:~$ sudo docker volume ls
DRIVER VOLUME NAME
local nexus-data
local test
(base) pang@pang-HP:~$
此时,查询volume中,并没有新增数据卷。
旧参数-v
使用-v
标记也可以指定挂载一个本地的已有目录到容器中去作为数据卷,如:
(base) pang@pang-HP:~$ sudo docker run -d --name centos -v /home/pang/vdata:/vdata centos:7 tail -f /dev/null
a1492463b9f56a8b6b67eb16093b22b27af619813989a1aff5b319e5f7fd8bae
(base) pang@pang-HP:~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1492463b9f5 centos:7 "tail -f /dev/null" 5 seconds ago Up 4 seconds centos
9a102684ab20 sonatype/nexus3 "sh -c ${SONATYPE_DI…" 24 hours ago Up 24 hours 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp, 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp nexus3
(base) pang@pang-HP:~$
此种方式不会创建数据卷,在volume无法查询到。
(base) pang@pang-HP:~$ sudo docker volume ls
DRIVER VOLUME NAME
local nexus-data
(base) pang@pang-HP:~$
通过查询容器配置,可以获取host目录与容器目录对应关系
(base) pang@pang-HP:~$ sudo docker inspect centos
...
"Mounts": [
{
"Type": "bind",
"Source": "/home/pang/vdata",
"Destination": "/vdata",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...
(base) pang@pang-HP:~$
同样,在容器目录中的变动会同步到host目录中。
(base) pang@pang-HP:~$ sudo docker exec -it centos /bin/bash
[root@a1492463b9f5 /]# cd /vdata
[root@a1492463b9f5 vdata]# touch aaa.txt
[root@a1492463b9f5 vdata]# ls
aaa.txt
[root@a1492463b9f5 vdata]# exit
exit
(base) pang@pang-HP:~$ ls /home/pang/vdata/
aaa.txt
(base) pang@pang-HP:~$
1.2.3 临时数据卷
# 使用--tmpfs
docker run -dit --name tmpfs-test --tmpfs /app busybox
1.2.4 挂载一个本地主机文件作为数据卷
-v
标记也可以从主机挂载单个文件到容器中作为数据卷:
#记录在容器中输入过的命令历史
sudo docker run --rm -it -v ~/.bash_history : ~/.bash_history ubuntu /bin/bash
如果直接挂载一个文件到容器,使用文件编辑工具,包括vi
或者sed --in -place
的时候,可能会造成文件inode的改变,从Docker1.1.0起,这会导致报错误信息。所以推荐的方式是直接挂载文件所在的目录。
2 数据卷容器
如果需要在容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷其实就是一个普通的容器,专门用它提供数据卷供其他容器挂载使用。
- 创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata。
sudo docker run -it -v /dbdata --name dbdata ubuntu
- 可以在其他容器中使用–volumes-from来挂载dbdata容器中的数据卷。如:
sudo docker run -it --volumes-from dbdata --name db1 ubuntu
sudo docker run -it --volumes-from dbdata --name db2 ubuntu
此时,容器db1和db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任何一方在该目录下的写入,其他容器都可以看到。
可以多次使用–volumes-from参数来从多个容器挂载多个数据卷。还可以从其他已经挂载了容器卷的容器来挂载数据卷:
sudo docker run -d --name db3 --volumes-from db1 training/postgres
如果删除了挂载的容器(包括dbdata,db1和db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用docker rm -v 命令来指定同时删除关联的容器。
3 利用数据卷容器来迁移数据
可以利用数据卷容器对其中的数据卷进行备份,恢复,以实现数据的迁移。
3.1 备份
使用下面的命令来备份dbdata数据卷容器内的数据卷:
sudo docker run --volumes-from dbdata -v ${pwd}:/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata
这个命令稍微有点复杂,具体分析下:
- 首先利用ubuntu镜像创建了一个容器worker。 使用
--volumes-from dbdata
参数来让worker容器挂载dbdata容器的数据卷(即 dbdata数据卷; - 使用
-v $ (pwd):/backup
参数来挂载本地的当前目录到worker容器的/backup
目录; - worker容器启动后,使用
tar cvf /backup/backup.tar /dbdata
命令将/dbdata
下内容备份为容器内的/backup/backup. tar
,即宿主主机当前目录下的`backup.tar。
3.2 恢复
如果要恢复数据到一个容器,可以按照下面的操作。
- 创建一个带有数据卷的容器dbdata2:
sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
- 然后创建另一个新的容器,挂载dbdata2的容器,并使用untar解压备份文件到所挂载的容器卷即可:
sudo docker run --volumes-from dbdata2 -v ${pwd}:/backup busybox tar xvf /backup/backup.tar