Docker 数据卷管理及优化
Docker 数据卷是一个可供容器使用的特殊目录,它绕过了容器的文件系统,直接将数据存储在宿主机上。通过数据卷,可以实现数据的持久化、共享以及独立于容器生命周期的管理。
1.1 为什么要用数据卷
Docker 分层文件系统的特点
-
性能差:Docker 的分层文件系统(Union File System)在写入操作时会创建新的层,导致性能下降。
-
生命周期与容器相同:容器删除后,其文件系统中的数据也会丢失。
Docker 数据卷的优势
-
绕开分层文件系统:数据卷直接挂载到宿主机的文件系统中,性能与宿主机磁盘相同。
-
数据持久化:即使容器被删除或重新创建,数据卷中的数据仍然存在,不会丢失。
-
数据共享:多个容器可以同时挂载同一个数据卷,实现数据的共享和交互。
-
独立于容器生命周期:数据卷的生命周期独立于容器,不受容器的启动、停止和删除的影响。
Docker 提供了两种卷类型:
-
Bind Mount:将主机上的目录或文件挂载到容器中。
-
Docker Managed Volume:由 Docker 自动管理的数据卷,不需要指定挂载源。
1.2 Bind Mount 数据卷
特点
-
将主机上的目录或文件挂载到容器中。
-
使用直观高效,易于理解。
-
使用
-v
选项指定路径,格式为<host path>:<container path>
。 -
如果
-v
选项指定的路径不存在,挂载时会自动创建。
注意事项
1. “如果挂载的路径在宿主机上不存在,Docker 会自动创建该路径。”
这句话的意思是:当你使用绑定挂载(bind mount)时,如果宿主机上的目录路径不存在,Docker 会自动创建这个目录。
举例说明:
假设你运行以下命令:
docker run -d --name my_container -v /haha/test:/container/path nginx:1.23
-
如果宿主机上
/haha/test
目录不存在,Docker 会自动创建/haha/test
目录。 -
这个行为是为了确保挂载操作能够成功执行,因为挂载需要一个有效的宿主机路径。
2. “如果需要挂载的文件或目录在宿主机上不存在,可能会导致容器启动失败。”
这句话的意思是:如果你尝试挂载一个文件,而这个文件在宿主机上不存在,Docker 会报错并导致容器启动失败。
举例说明:
假设你运行以下命令:
docker run -d --name my_container -v /haha/test/file.txt:/container/file.txt nginx:1.23
-
如果宿主机上
/haha/test/file.txt
文件不存在,Docker 会报错,因为 Docker 不会自动创建文件。它只会自动创建目录,而不会创建文件。 -
错误信息可能类似于:
lstat /haha/test/file.txt: no such file or directory
-
这种情况下,容器无法启动,因为挂载操作失败了。
总结:(自动创建的是目录,而不是文件)
-
目录:如果挂载的路径(目录)在宿主机上不存在,Docker 会自动创建该目录。
-
文件:如果挂载的文件在宿主机上不存在,Docker 不会自动创建文件,而是会报错并可能导致容器启动失败。
1.3 Docker Managed 数据卷
特点
-
不需要指定挂载源,Docker 自动为容器创建数据卷目录。
-
默认创建的数据卷目录位于
/var/lib/docker/volumes
中。 -
如果挂载时指向容器内已有的目录,原有数据会被复制到数据卷中。
示例
1. 不需要指定挂载源,Docker 自动为容器创建数据卷目录
命名卷由 Docker 自动管理,不需要指定宿主机上的路径。当你在运行容器时使用命名卷时,Docker 会自动创建一个卷,并将其挂载到容器内的指定路径。
举例说明:
docker run -d --name my_container -v my_volume:/container/path nginx:1.23
-
在这个例子中,
my_volume
是一个命名卷的名称。 -
Docker 会自动在内部存储中创建一个名为
my_volume
的卷,并将其挂载到容器内的/container/path
。 -
你不需要指定宿主机上的路径,Docker 会管理这个卷的存储位置。
2. 默认创建的数据卷目录位于 /var/lib/docker/volumes
中
Docker 管理的命名卷默认存储在宿主机的 /var/lib/docker/volumes
目录下。每个命名卷都有一个独立的目录,用于存储数据。
举例说明:
假设你创建了一个名为 my_volume
的命名卷,Docker 会在 /var/lib/docker/volumes
下创建一个对应的目录:
/var/lib/docker/volumes/my_volume/_data
-
_data
目录是实际存储卷数据的地方。 -
你可以通过以下命令查看所有命名卷:
docker volume ls
-
如果需要查看卷的具体存储位置,可以运行:
docker volume inspect my_volume
3. 如果挂载时指向容器内已有的目录,原有数据会被复制到数据卷中
当你将一个命名卷挂载到容器内的某个路径时,如果该路径在容器中已经存在并且包含数据,Docker 会将这些数据复制到命名卷中。这个过程称为“数据初始化”。
举例说明:
假设你运行以下命令:
docker run -d --name my_container -v my_volume:/container/existing/path nginx:1.23
-
如果
/container/existing/path
在容器中已经存在,并且包含一些文件或目录,Docker 会在第一次挂载时将这些内容复制到my_volume
中。 -
之后,无论何时重新挂载该卷,容器内的
/container/existing/path
都会指向my_volume
,并且数据会保持一致。
注意:
-
这个数据复制的过程只会在第一次挂载时发生。
-
如果命名卷已经存在并且包含数据,Docker 不会覆盖卷中的数据,而是会直接使用卷中的数据。
清理未使用的 Docker 数据卷
[root@docker ~]# docker volume prune
注意:
在执行
docker volume prune
命令之前,请确保你确实不再需要这些数据卷中的数据,因为该操作是不可逆的,一旦删除数据将无法恢复。如果有重要的数据存储在数据卷中,建议先进行备份,或者确保数据已经被妥善保存到其他地方。
建立数据卷
[root@docker ~]# docker volume create leevol1
[root@docker ~]# ls -l /var/lib/docker/volumes/leevol1/_data/
查看卷
[root@docker ~]# docker volume ls
DRIVER VOLUME NAME
local leevol1
使用建立的数据卷
[root@docker _data]# docker run -d --name web1 -p 80:80 -v leevol1:/usr/share/nginx/html nginx
e76706848323d6c329c41c4140903f8cc441458daf1459d9016bd1ed0ab3360a
root@docker _data]# cd /var/lib/docker/volumes/leevol1/_data
[root@docker _data]# ls
[root@docker _data]# echo leevol1 > index.html
[root@docker _data]# curl 172.25.254.100
leevol1
1.4 数据卷容器(Data Volume Container)
数据卷容器(Data Volume Container)是 Docker 中一种特殊的容器,主要用于方便地在多个容器之间共享数据卷。
建立数据卷容器
[root@docker ~]# docker run -d --name datavol \
-v /tmp/data1:/data1:rw \
-v /tmp/data2:/data2:ro \
-v /etc/resolv.conf:/etc/hosts busybox
使用数据卷容器
[root@docker ~]# docker run -it --name test --rm --volumes-from datavol busybox
/ # ls
bin data1 data2 dev etc home lib lib64 proc root sys tmp usr var
/ # cat /etc/resolv.conf
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.
nameserver 114.114.114.114
search timinglee.org
# Based on host file: '/etc/resolv.conf' (legacy)
# Overrides: []
/ # touch data1/leefile1
/ # touch /data2/leefile1
touch: /data2/leefile1: Read-only file system
/ #
数据卷容器的优势
-
方便共享:通过数据卷容器,可以在多个容器之间轻松共享数据卷。
-
简化管理:数据卷容器可以集中管理数据卷,便于维护和迁移。
1.5 Bind Mount 数据卷和 Docker Managed 数据卷的对比
相同点
-
两者都是基于宿主机文件系统中的某个路径。
不同点
特性 | Bind Mount 数据卷 | Docker Managed 数据卷 |
---|---|---|
路径指定 | 必须指定宿主机路径 | 不需要指定宿主机路径,由 Docker 自动管理 |
移植性 | 依赖宿主机路径,移植性较差 | 独立于宿主机路径,移植性较好 |
管理方式 | 需要手动管理宿主机路径 | 由 Docker 自动管理,支持 docker volume 命令 |
性能 | 与宿主机磁盘性能相同 | 与宿主机磁盘性能相同 |
适用场景 | 适合需要直接访问宿主机文件的场景 | 适合需要在多个容器之间共享数据的场景 |
1.6 备份与迁移数据卷
备份数据卷
# 建立容器并指定使用卷到要备份的容器
[root@docker ~]# docker run --volumes-from datavol \
-v `pwd`:/backup busybox \ # 把当前目录挂载到容器中用于保存备份数据
tar zcf /backup/data1.tar.gz /data1 # 备份数据到本地
数据恢复
docker run -it --name test -v leevol1:/data1 -v `pwd`:/backup busybox /bin/sh -c "tar zxf /backup/data1.tar.gz;/bin/sh"
/ # ls
backup data1 etc lib proc sys usr
bin dev home lib64 root tmp var
/ # cd data1/ # 查看数据迁移情况
/data1 # ls
index.html leefile1
注意事项
-
在备份和恢复数据卷时,确保路径正确,避免数据丢失。
-
如果数据卷较大,备份和恢复过程可能需要较长时间,请耐心等待。