数据卷是为了保存用户需要保存的数据
数据卷挂载
#创建数据存储文件
[root@docker docker]#mkdir -p /web/app
#创建挂载容器
[root@docker docker]#docker run -it --name volume -v /web/app centos
[root@docker docker]# docker run -it -d centos /bin/bash
d1eb81de80ec6e8e442f0ad6ba195c3e31d37ef9628317d823dfc8baa715f09b
[root@docker docker]# ls /web
app
查看挂载信息
docker inspect volume
[root@docker docker]# docker inspect volume
......
"Mounts": [
{
"Type": "volume",
"Name": "c46e1c050f9f5820ed9d764d9e2bf291db45040c3b38f47ab7e3a92d0281f4df",
"Source": "/var/lib/docker/volumes/c46e1c050f9f5820ed9d764d9e2bf291db45040c3b38f47ab7e3a92d0281f4df/_data",
"Destination": "/web/app",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
.....
宿主机在/var/lib/docker/volumes/下自动生成了挂载目录
手动指定挂载目录
-v 宿主机目录(或文件)路径:容器内映射路径
例如:
[root@docker docker]# docker run \
> -v /web/app:/app \
> -it -d --name test nginx /bin/bash
50bfd04e58307dba9b9edee9cbf58254f0bbb2b2508db76169fd4705631e053f
docker inspect
查看容器test 状态及挂载信息
[root@docker docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
50bfd04e5830 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp test
[root@docker docker]# docker inspect test
.....
"Mounts": [
{
"Type": "bind",
"Source": "/web/app",
"Destination": "/app",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
.....
进入test容器
[root@docker docker]# docker attach test
root@50bfd04e5830:/# ls /
app boot docker-entrypoint.d etc lib media opt root sbin sys usr
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
root@50bfd04e5830:/#
root@50bfd04e5830:/# ls /app/
可以看到容器内根目录下有新的/app目录,并且没有内容
接下来
#宿主机操作
[root@docker ~]# cd /web/app/
[root@docker app]# touch a.txt b.txt
[root@docker app]# ls
a.txt b.txt
#容器内查看
root@50bfd04e5830:/# ls /app/
a.txt b.txt
root@50bfd04e5830:/#
可以发现挂载目录数据同步
设置权限
如果需要为数据卷设置只读权限:
[root@docker app]# docker run -it --name volume -v /src/test:/webapp:ro nginx /bin/bash
-v /src/test:/webapp:ro
将数据卷权限设置为ro(只读)
查看挂载情况
[root@docker app]# docker inspect volume
....
"Mounts": [
{
"Type": "bind",
"Source": "/src/test",
"Destination": "/webapp",
"Mode": "ro",
"RW": false,
"Propagation": "rprivate"
}
],
...
发现为ro只读模式
使用DOckerfile 挂载数据卷
用户创建镜像时,通常会在Dockerfile文件中加上 VOLUME[/date]来创建含有数据卷的镜像,并使用该镜像创建包含数据卷的容器。
Dockerfile可以创建多个数据卷,与使用docker run命令创建数据卷不同,Dockerfile中的数据卷不能映射到已经存在的本地目录。在启动容器时,才会创建Dockerfile中指定的数据卷,并且以Dockerfile中指定的名称命名。运行同样镜像的容器创建的数据卷是不一样的(可以看到不同容器的数据卷地址也是不一样的)。当容器中的数据卷地址不一样时,容器之间就无法共享数据了。
下面使用Dockerfile中的VOLUME选项来指定挂载数据卷,首先创建Dockerfile并添加内容,
示例代码如下:
[root@docker ~]# vi Dockerfile
FROM centos-ali/vim
VOLUME /root/data
VOLUME /work
VOLUME test
以上示例创建了一个Dockerfile文件并添加了内容,即挂载三个数据卷。
接下来根据这个创建新镜像
[root@docker ~]# docker build -t volume .
[+] Building 0.2s (5/5) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 100B 0.0s
=> [internal] load metadata for docker.io/centos-ali/vim:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [1/1] FROM docker.io/centos-ali/vim:latest 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:c786f7195633b904411d82fe8fadbe470302f85e95048b0561d9c0e762a32c32 0.0s
=> => naming to docker.io/library/volume
以上示例中,镜像已经构建完成,并且执行了挂载三个数据卷的命令。
下面使用构建完成的镜像运行容器,并查看其挂载信息,示例代码如下:
[root@docker ~]# docker run -it volume
[root@34dd09f6449c /]# ls
bin etc lib lost+found mnt proc run srv test usr work
dev home lib64 media opt root sbin sys tmp var
[root@34dd09f6449c /]# exit
exit
#退出后查看挂载情况
[root@docker ~]# docker inspect 34d
....
"Mounts": [
{
"Type": "volume",
"Name": "8082f8bf30382b5eff4ca43d5aed94b339dc124d63739ea6fcc5f2dd3e1759f5",
"Source": "/var/lib/docker/volumes/8082f8bf30382b5eff4ca43d5aed94b339dc124d63739ea6fcc5f2dd3e1759f5/_data",
"Destination": "/work",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
.....
从以上示例中可以看出,该容器挂载了三个数据卷,容器内的目录为Dockerfile中指定的目录,宿主机中数据卷的位置在/var/lib/docker/volumes/
下,并且数据卷的地址是随机生成的。
如此一来,就实现了通过Dockerfile创建镜像,运行容器时会自动挂载数据卷。
数据卷容器
运行容器时宿主机会随机生成挂载目录,无法保持目录地址一致,所以无法实现容器间的数据共享。数据卷容器可以有效地解决这个问题:将已命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器叫作数据卷容器。数据卷容器挂载一个宿主机目录,其他容器连接数据卷容器来实现数据的共享
下面启动一个名为 volume-container的容器,此容器包含两个数据卷/volumel和/volume2(这两个数据卷目录在容器中,运行容器时会自动创建),示例代码如下:
[root@docker ~]# docker run -it --name volume-container -v /volume1 -v /volume2 centos
[root@f8d3844af4b9 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume2
dev home lib64 media opt root sbin sys usr volume1
以上示例中,容器volume-container已经创建完成,数据卷也挂载完成。下面使用Ctrl+P+Q组合键退出当前容器终端,查看挂载信息并在宿主机中为数据卷添加文件,示例代码如下:
[root@docker ~]# docker inspect volume-container | grep volume
"Name": "/volume-container",
"Type": "volume",
"Source": "/var/lib/docker/volumes/6aac0390812b71d45ac1bde6e65758215cabbd305a580d6d91963f5530905d59/_data",
"Destination": "/volume1",
"Type": "volume",
"Source": "/var/lib/docker/volumes/897ee8fcdbf3d866d78973d996069e8c1ea3a63f136c0e10afcbb10f099e9b16/_data",
"Destination": "/volume2",
"/volume1": {},
"/volume2": {}
#查看挂载信息
[root@docker ~]# cd /var/lib/docker/volumes/6aac0390812b71d45ac1bde6e65758215cabbd305a580d6d91963f5530905d59/_data/
[root@docker _data]# ls
[root@docker _data]# echo hello container1 >a.txt
[root@docker _data]# cd /var/lib/docker/volumes/897ee8fcdbf3d866d78973d996069e8c1ea3a63f136c0e10afcbb10f099e9b16/_data/
[root@docker _data]# echo hello container2 >b.txt
以上示例在宿主机中分别为两个数据卷添加文件及文件内容。
下面创建容器 testl-container,用-volumes-from,参数挂载容器 volume-container中的数据卷,示例代码如下:
[root@docker _data]# docker run -it --name test1-container --volumes-from volume-container centos
[root@b542374e57df /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume2
dev home lib64 media opt root sbin sys usr volume1
[root@b542374e57df /]# cat /volume1/a.txt
hello container1
[root@b542374e57df /]# cat /volume2/b.txt
hello container2
从以上示例中可以看出,两个容器实现了数据共享。
下面将初始数据卷容器删除,观察数据卷还能否正常工作,示例代码如下:
[root@docker _data]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b542374e57df centos "/bin/bash" 4 minutes ago Up 3 minutes test1-container
f8d3844af4b9 centos "/bin/bash" 28 minutes ago Up 28 minutes volume-container
[root@docker _data]# docker stop volume-container
volume-container
#删除了数据卷容器
[root@docker _data]# docker rm volume-container
volume-container
[root@docker _data]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b542374e57df centos "/bin/bash" 4 minutes ago Up 4 minutes test1-container
[root@docker _data]# docker run -it --name test2-container --volumes-from test1-container centos
[root@a7dba2da7acf /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume2
dev home lib64 media opt root sbin sys usr volume1
[root@a7dba2da7acf /]# cat /volume1/a.txt
hello container1
[root@a7dba2da7acf /]# cat /volume2/b.txt
hello container2
从以上示例中可以看到,即使删除了初始的数据卷容器volume-container或其他容器,只要有容器在使用该数据卷,里面的数据就不会丢失。
下面删除所有容器,再观察数据卷,示例代码如下:
#删除所有容器
[root@docker _data]# docker rm `docker ps -a | grep Exited|awk '{print $1}'
#查看数据`
[root@docker _data]# cd /var/lib/docker/volumes/897ee8fcdbf3d866d78973d996069e8c1ea3a63f136c0e10afcbb10f099e9b16/_data/
[root@docker _data]# ls
b.txt
[root@docker _data]# cat b.txt
hello container2
#数据还在
备份数据卷
企业中,业务数据不容有失。人们通常会对数据进行一次备份或多次备份,以保证数据的安全性。
下面创建一个名为data- volume的 CentOS容器,准备对其挂载的两个数据卷/var/volume1和/var/volume2进行备份操作。示例代码如下:
[root@docker _data]# docker run -it --name data-volume -v /var/volume1 -v /var/volume2 centos
[root@ee9bc9586288 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@ee9bc9586288 /]# ls /var
adm crash empty games kerberos local log nis preserve spool volume1 yp
cache db ftp gopher lib lock mail opt run tmp volume2
以上示例中,容器已经创建完成,数据卷也成功挂载。
下面在容器挂载目录中创建文件并添加内容,示例代码如下:
[root@ee9bc9586288 /]# echo hello container1 >/var/volume1/a.txt
[root@ee9bc9586288 /]# echo hello container1 >/var/volume2/b.txt
[root@ee9bc9586288 /]# echo hello container2 >/var/volume2/b.txt
[root@ee9bc9586288 /]# cat /var/volume1/a.txt
hello container1
[root@ee9bc9586288 /]# cat /var/volume2/b.txt
hello container2
简而言之,备份数据卷就是使用 -volumes-from
参数来创建一个挂载数据卷的容器,从宿主机挂载要存放备份数据的目录到容器的备份目录,并备份数据卷中的数据。完成后使用-rm
参数删除容器。此对备份数据已经保存在当前的目录下。示例代码如下:
#先退出容器
[root@ee9bc9586288 /]# exit
exit
#创建一个用于数据备份的容器
[root@docker _data]# docker run --rm --volumes-from data-volume -v /root/back:/backup centos tar cvf /backup/backup1.tar /var/volume1
#--rm 备份运行完,自动删除自己(数据备份服务器)
#挂载宿主机/root/backup到容器/backup
tar: Removing leading `/' from member names
/var/volume1/
/var/volume1/a.txt
[root@docker _data]# docker ps -a
#发现只有数据备份的目标容器,执行命令的容器自动删除了
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ee9bc9586288 centos "/bin/bash" 13 minutes ago Exited (127) 2 minutes ago data-volume
#文件仍然存在
[root@docker _data]# ls /root/back/
backup1.tar
管理数据卷
与容器关联
数据卷最大的优势是可以用来做持久化数据。它的生命周期是独立的,Docker
不会在容器被删除后自动删除数据卷,也不存在类似垃圾回收的机制来处理没有
被任何容器使用的数据卷。但难免会有无用的数据卷,用户可以通过在删除容器
的命令中添加参数,在删除容器的同时删除数据卷。
Docker数据卷可以通过命令与容器关联,删除容器时,数据卷也随之被删除。
docker rm-v
删除容器时添加-v参数会将数据卷一并删除。
docker run--rm
创建、运行容器时添加-rm参数,容器运行结束时容器与数据卷会被一并删除。
如果不对数据卷进行及时清理,/var/lib/docker/volumes/目录下就会产生许多残留目录。
但删除的数据卷是无法找回的,建议再三确认之后再执行操作。
命令管理
Docker中有专门的容器数据卷命令供用户管理容器数据卷。下面通过示例介绍容器数据卷命的一些参数。
创建数据卷
docker volume create
:创建数据卷
示例代码如下:
[root@docker _data]# docker volume create test
test
列出数据卷
docker volume ls
:列出数据卷
[root@docker _data]# docker volume ls
DRIVER VOLUME NAME
local 5e438f486323a1b43a088dae231c5936b724f9eed09334102ccf9ef0104e67c6
local 6aac0390812b71d45ac1bde6e65758215cabbd305a580d6d91963f5530905d59
local 8e2ff58f7069342ea9efdee1c335bdc7f1d9272ea1e2a14ea8da386482896f29
local 897ee8fcdbf3d866d78973d996069e8c1ea3a63f136c0e10afcbb10f099e9b16
local 8082f8bf30382b5eff4ca43d5aed94b339dc124d63739ea6fcc5f2dd3e1759f5
local 9746d50c43550621c70b69a728798eafbbfc4206e95e959ce50376df9de88347
local a459847e1c3b220931bfefd20266c6da7fc7f148ffc2802b05e32900daafc756
local c46e1c050f9f5820ed9d764d9e2bf291db45040c3b38f47ab7e3a92d0281f4df
也可在挂载目录查看
[root@docker _data]# ls /var/lib/docker/volumes/
5e438f486323a1b43a088dae231c5936b724f9eed09334102ccf9ef0104e67c6
6aac0390812b71d45ac1bde6e65758215cabbd305a580d6d91963f5530905d59
8082f8bf30382b5eff4ca43d5aed94b339dc124d63739ea6fcc5f2dd3e1759f5
897ee8fcdbf3d866d78973d996069e8c1ea3a63f136c0e10afcbb10f099e9b16
8e2ff58f7069342ea9efdee1c335bdc7f1d9272ea1e2a14ea8da386482896f29
9746d50c43550621c70b69a728798eafbbfc4206e95e959ce50376df9de88347
a459847e1c3b220931bfefd20266c6da7fc7f148ffc2802b05e32900daafc756
backingFsBlockDev
c46e1c050f9f5820ed9d764d9e2bf291db45040c3b38f47ab7e3a92d0281f4df
metadata.db
test
列出数据卷
docker inspect <容器id或名字>
:列出数据卷
[root@docker _data]# docker inspect test
...
"Mounts": [
{
"Type": "bind",
"Source": "/web/app",
"Destination": "/app",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...
删除一个或多个数据卷
docker volume rm <数据卷name>
:删除一个或多个数据卷
#需要先终止并删除容器
docker stop <容器id或名字>
docker rm <容器id或名字>
#删除数据卷
docker volume rm <数据卷name>
删除所有未被使用的数据卷
docker volume prune
:删除所有未被使用的数据卷
Comments NOTHING