参考资料
- 《docker volume》
- 《docker容器的数据卷以及使用方式》
Docker容器默认把数据存储到容器内部,当容器删除的时候,容器内的数据会同步删除。
很多情况下,我们是不希望数据被删除的,常规的有2种方式能达到目的:
- 在删除容器之前将数据拷贝到本地。
- 通过数据卷把宿主机文件夹映射到容器内部,这就是数据卷。
Docker数据卷种类和特点
Docker数据卷(Volume)有两种:
- 数据卷
- 数据卷容器
数据卷是特殊设计的目录,独立在容器的生命周期外,可以绕过联合文件系统(UnionFS),可以为一个或多个容器提供服务。
Docker数据卷的特点:
- 可以在容器和宿主机之间或容器与容器之间共享和重用;
- 在容器和宿主机之间双向同步;
- 数据卷大小不会附加到容器上;
- 数据卷的变化,不会影响镜像的更新;
- 会一直存在,直到没有任何容器使用它,才能使用命令
docker volume rm [volumes名字]
删除。
数据卷大小不会附加到容器上,这就类似软链接。可以启动两个Tomcat,并把其中一个Tomcat的logs目录挂载进去,分别通过
docker export
导出,发现挂载logs目录的导出文件中logs目录没文件,未挂载logs目录的,导出文件中有文件。
Docker数据卷
挂载
Docker使用-v
指令挂载数据卷,挂载多个时,使用多个-v
指令。
Docker数据卷挂载常规的有3种方式:
- 指定目录挂载
- 匿名挂载
- 具名挂载
指定目录挂载
在挂载数据卷时,指定宿主机目录:容器目录。Docker不会自动在安装目录下创建数据卷。
- 语法
# -v 为挂载目录选项
docker run -v 宿主机目录:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
- 示例
# 启动tomcat,并给tomcat挂载日志目录
# -d 后台运行
# --name tomcat 指定别名
# -P 随机指定端口,启动后可通过docker ps命令查看映射的端口
# -v 宿主机目录:容器目录 挂载目录到容器
docker run -d --name tomcat -P -v /home/docker/volumes/tomcat/logs:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
注意:指定目录挂载,不能使用
./
相对路径,可以使用~/
相对路径。
./
表示当前路径下的目录;~/
表示用户主目录,也就是登录系统后直接进入的目录。
- 分析
Tomcat启动后,就可以在/home/docker/volumes/tomcat/logs目录中看到有日志文件生成。
进入容器,也能看到日志文件,说明挂载成功。
# 进入容器内部
# -it 交互模型运行
# /bin/bash 以/bin/bash交互
docker exec -it tomcat /bin/bash
此时在宿主机或容器中修改文件,另外一边都能看到,说明是双向同步的。
使用docker inspect
查看容器元数据,在Mounts
节点下可以看到挂载的数据卷。
# 查看容器元数据
# 输出
...
"Mounts": [
{
"Type": "bind",
"Source": "/home/docker/volumes/tomcat/logs",
"Destination": "/usr/local/tomcat/logs",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...
使用docker volume ls
命令查看Docker所有挂载的数据卷,发现并没有找到这个挂载的数据卷。说明指定目录挂载方式并不会把数据卷信息存储到Docker中,也就是并不能通过具名或匿名挂载方式复用该数据卷。
# 查看所有挂载的数据卷
docker volume ls
# 输出
DRIVER VOLUME NAME
local 0ea11ee5a377263e6a62a61afdd554f12f3f61e0e69fb603794363637668f270
local 28ad647f7dc23b3a04c96f8ba8eeca08c0766a1b2669bc42162e43ddcd585164
local 85a5ba99cf1ca1a52e745685bede94be81f6d79e44ef108192d2d27817460331
要想多个Tomcat共用这个数据卷,那么就只能重新输入完整的宿主机文件路径来挂载。
# 复用数据卷
# -v 后面跟的是完整的宿主机文件路径:容器目录
docker run -d --name tomcat1 -P -v /home/docker/volumes/tomcat/logs:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
匿名挂载
在挂载数据卷时,只指定容器内部的目录。Docker会自动将数据卷用一串很长的字符命名。
- 语法
docker run -v 容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
- 示例
# 启动tomcat,并给tomcat挂载日志目录
# -v后只指定容器内部目录
docker run -d --name tomcat -P -v /usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
- 分析
使用docker volume ls
命令查看,发现多了一个数据卷,数据卷名称是一串很长的字符。
# 查看所有数据卷
docker volume ls
# 输出
DRIVER VOLUME NAME
local 0ea11ee5a377263e6a62a61afdd554f12f3f61e0e69fb603794363637668f270
local 2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4
local 28ad647f7dc23b3a04c96f8ba8eeca08c0766a1b2669bc42162e43ddcd585164
local 85a5ba99cf1ca1a52e745685bede94be81f6d79e44ef108192d2d27817460331
使用docker volume inspect 数据卷ID
命令查看数据卷详情,发现数据卷在Docker目录下。
# 查看数据卷元数据
docker volume inspect 2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4
# 输出
[
{
"CreatedAt": "2020-08-07T12:05:52+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4/_data",
"Name": "2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4",
"Options": null,
"Scope": "local"
}
]
使用ls
命令查看目录内容,发现里面有Tomcat的日志文件,说明挂载成功了。
# 查看目录内容
ls /var/lib/docker/volumes/2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4/_data
# 输出
catalina.2020-08-07.log host-manager.2020-08-07.log localhost.2020-08-07.log localhost_access_log.2020-08-07.txt manager.2020-08-07.log
使用docker volume rm 数据卷ID
删除,发现删不掉。
# 删除数据卷
docker volume rm 2afdddef007505f06bc4d83bc157c2b6250661c560c7650b9bd1b2f988bd43d4
停止并删除容器后,发现可以删除成功,说明,只要数据卷还在被使用(或引用)就不能删除。
具名挂载
在挂载数据卷时,指定数据卷名称:容器内部的目录。Docker会按照指定的数据卷名称命名。
语法
docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
# 或
docker volume create 数据卷名称
docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
示例
# 启动tomcat,并给tomcat挂载日志目录
# -v后指定数据卷名称:容器内部目录
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
具名挂载和指定目录挂载对比
具名挂载:
- 数据卷命名规则:
[a-zA-Z0-9][a-zA-Z0-9_.-]
,只能以字母或数据开头,不能包含/
或~/
。- 具名挂载会在Docker目录下生成自定义名称的数据卷,可以使用
docker volume ls
查看。指定目录挂载:
- 数据卷是一个完整的路径,也就是以
/
或~/
开头的。- 指定目录挂载不会在Docker目录下生成数据卷。
挂载方式对比
挂载方式 | 生成数据卷 | 命名规则 | 默认名称 |
---|---|---|---|
指定目录挂载 | × | - | - |
匿名挂载 | √ | - | 随机字符串 |
具名挂载 | √ | [a-zA-Z0-9][a-zA-Z0-9_.-] |
指定的名称 |
Docker数据卷容器
如果一个非常复杂的容器,需要挂载很多个数据卷。如果这个容器要同时启动多个,一个个输入很长的挂载命令很容易出错。或者多个容器之间需要共享数据,此时就推荐使用数据卷容器了。
数据卷容器
数据卷容器就是挂载了数据卷的容器,数据卷容器可以被别的容器挂载。
数据卷容器的出现是为了解决容器之间数据共享问题。
数据卷容器的优势:
- 可以被多个容器简单的复用;
- 与数据卷容器是否启动无关。
数据卷容器使用
- 语法
docker run --volumes-from 数据卷容器 [OPTIONS] IMAGE [COMMAND] [ARG...]
- 示例
首先根据上面的示例,准备一个数据卷容器。
# 创建一个tomcat容器,并挂载数据卷
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
使用--volumes-from 数据卷容器
指令挂载这个数据卷容器。
# 启动tomcat,并给tomcat挂载数据卷容器
# 使用--volumes-from,挂载数据卷容器
docker run -d --name tomcat_link -P --volumes-from tomcat tomcat:8.5.57-jdk8-openjdk
挂载多个数据卷容器时,使用多个
--volumes-from 数据卷容器
指令挂载。
然后停用tomcat容器,tomcat_link容器还是能正常使用数据卷,说明数据卷容器是否启动,对使用者来说不影响。
命令集
挂载
指定目录挂载
- 语法
# -v 为挂载目录选项
docker run -v 宿主机目录:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
- 示例
# 启动tomcat,并给tomcat挂载日志目录
# -d 后台运行
# --name tomcat 指定别名
# -P 随机指定端口,启动后可通过docker ps命令查看映射的端口
# -v 宿主机目录:容器目录 挂载目录到容器
docker run -d --name tomcat -P -v /home/docker/volumes/tomcat/logs:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
匿名挂载
- 语法
docker run -v 容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
- 示例
# 启动tomcat,并给tomcat挂载日志目录
# -v后只指定容器内部目录
docker run -d --name tomcat -P -v /usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
具名挂载
- 语法
docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
# 或
docker volume create 数据卷名称
docker run -v 数据卷名称:容器目录 [OPTIONS] IMAGE [COMMAND] [ARG...]
- 示例
# 启动tomcat,并给tomcat挂载日志目录
# -v后指定数据卷名称:容器内部目录
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
数据卷容器挂载
- 语法
docker run --volumes-from 数据卷容器 [OPTIONS] IMAGE [COMMAND] [ARG...]
- 示例
# 创建一个tomcat容器,并挂载数据卷
docker run -d --name tomcat -P -v testvolume:/usr/local/tomcat/logs tomcat:8.5.57-jdk8-openjdk
# 启动tomcat,并给tomcat挂载数据卷容器
# 使用--volumes-from,挂载数据卷容器
docker run -d --name tomcat_link -P --volumes-from tomcat tomcat:8.5.57-jdk8-openjdk
说明:被挂载的Tomcat容器为正常的数据卷容器。
数据卷操作
创建数据卷:docker volume create
- 语法
docker volume create [OPTIONS] [VOLUME]
- 示例
# 创建一个匿名数据卷
docker volume create
# 创建一个testvolume数据卷
docker volume create testvolume
查看所有数据卷:docker volume ls
- 语法
docker volume ls [OPTIONS]
- 示例
# 查看所有数据卷
docker volume ls
查看指定数据卷元数据:docker volume inspect
- 语法
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
- 示例
# 查看testvolume数据卷元数据
docker volume inspect testvolume
删除数据卷:docker volume rm/prune
- 语法
# 删除一个或多个数据卷
docker volume rm [OPTIONS] VOLUME [VOLUME...]
# 删除所有未使用的数据卷
docker volume prune [OPTIONS]
- 示例
# 删除testvolume数据卷
docker volume rm testvolume
# 删除所有未使用的数据卷
docker volume prune