生产环境中使用docker的过程中,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。
容器中管理数据主要有两种方式:
- 数据卷(Data Volumes): 容器内数据直接映射到本地主机环境;
- 数据卷容器(Data Volume Containers): 使用特定容器维护数据卷。
本篇文章首先介绍如何在容器内创建数据卷,并且把本地的目录或文件挂载到容器内的数据卷中。接下来,会介绍如何使用数据卷容器在容器和主机、容器和容器之间共享数据,并实现数据的备份和恢复。
6.1 数据卷
数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似Linux中的mount操作。
数据卷可以提供很多有用的特性,如下所示:
- 数据卷可以在容器之间共享和重用,容器之间传递数据将变得高效方便;
- 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
- 对数据卷的更新不会影响镜像,解耦了应用和数据;
- 卷会一直存在,知道没有容器使用,可以安全的卸载它。
1.在容器内创建一个数据卷
在用docker run
命令的时候,使用-v
标记可以在容器内创建一个数据卷。多次重复-v
标记可以创建多个数据卷。
下面 使用webserver
镜像创建一个web容器,并创建一个数据卷挂载到容器的/webapp
目录。
[root@private_vpn ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
webserver v0.21 e230d26d7671 2 hours ago 967.9 MB
centos6.8 0.21 7e48bfa0489e 30 hours ago 1.052 GB
[root@private_vpn ~]# docker run -itd -p 80:80 --name web -v /tmp/webapp:/webapp webserver:v0.21 /bin/bash
71cf8102d33c8e2a5ddfb69ed28bf8743ee4c1dbc27c9c6fd0a69c1d97b74d58
[root@private_vpn ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
71cf8102d33c webserver:v0.21 "/bin/bash" 4 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp web
[root@private_vpn ~]#
[root@private_vpn ~]# ls -l /tmp/webapp/
total 0
[root@private_vpn ~]# docker exec -ti 71 /bin/bash
[root@71cf8102d33c /]# ls -l /webapp
total 0
[root@71cf8102d33c /]# cat /tmp/test.txt #容器讲解那篇文章创建的测试文件
test
命令:docker run -itd -p 80:80 --name web -v /tmp/webapp:/webapp webserver:v0.21 /bin/bash
使用-v
标记指定挂载一个本地的已有目录到容器中去作为数据卷(推荐方式)
上面的命令加载主机的/tmp/webapp目录到容器的/webapp目录。
注意:本地路径必须是绝对路径且存在,如果目录不存在docker容器,则会自动创建。
-p: 指定端口映射,本地到docker容器。
--name: 指定容器名字
在主机/tmp/webapp目录下创建文件并写入内容:
[root@private_vpn ~]# cd /tmp/webapp/
[root@private_vpn webapp]# ls
[root@private_vpn webapp]# echo "This is a docker web test page" >> index.html
[root@private_vpn webapp]# cat index.html
This is a docker web test page
docker容器内检查数据是否已共享:
[root@71cf8102d33c webapp]# cat index.html
This is a docker web test page
数据已共享,在主机和容器之间。
然后再访问试试看(当然我的此容器内已经安装好了nginx服务,根据需求自己修改配置):
已经成功。
也可以先创建数据卷,然后在启动容器的时候挂载数据卷
docker volume create my-vol
同样可以通过inspect
命令查看数据卷详细信息
可以看到在/data/docker/volumes/
目录下创建一个数据卷my-vol(我之前修改了Docker Root Dir的目录为/data/docker/
)
[root@test ~]# docker volume create my-vol
my-vol
[root@test ~]# docker volume ls
DRIVER VOLUME NAME
local my-vol
[root@test ~]# docker volume inspect my-vol
[
{
"CreatedAt": "2020-01-08T13:39:54+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/data/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
启动一个挂载数据卷的容器:在用docker run
命令的时候,使用--mount
或者-v
标记来将数据卷
挂载到容器里。下面创建一个名为本web的容器,并加载一个数据卷到容器的/usr/share/nginx/html
目录。
docker run -d -p 8080:80 --name web -v my-vol:/usr/share/nginx/html nginx
[root@test ~]# docker run -d -p 8080:80 --name web -v my-vol:/usr/share/nginx/html nginx
f1ae7c82566a0bdb60931a8403b4ff6f72fd09673d0e586dac3ac11c49dc22ea
[root@test ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f1ae7c82566a nginx "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp web
运行完成后,可以查看数据卷目录下面已经有文件了。
[root@test ~]# ls -l /data/docker/volumes/my-vol/_data/
total 8
-rw-r--r-- 1 root root 494 Nov 19 20:50 50x.html
-rw-r--r-- 1 root root 612 Nov 19 20:50 index.html
添加文件并测试访问
[root@test ~]# cd /data/docker/volumes/my-vol/_data/
[root@test _data]# vim 1.html
[root@test _data]# cat 1.html
my-vol haha
[root@test _data]# curl localhost:8080/1.html
my-vol haha
数据卷时被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷
。如果需要在删除容器的同时移除数据卷,可以在删除容器的时候使用docker rm -v
这个命令。无主的数据卷可能会占据很多存储空间,需要清理请使用docker volume prune
命令。
挂载权限
默认挂载的路径权限为读写。如果指定为只读可以用:ro,如:-v /tmp:/usr/tmp:ro。
– 容器目录不可以为相对路径
– 宿主机目录如果不存在,则会自动生成
– 挂载宿主机已存在目录后,在容器内对其进行操作,报“Permission denied”。可通过两种方式解决:
* 1> 关闭selinux。
临时关闭:`# setenforce 0`
永久关闭:修改`/etc/sysconfig/selinux`文件,将 SELINUX 的值设置为disabled。
* 2> 以特权方式启动容器
指定`--privileged`参数,如:
`# docker run -it --privileged=true -v /test:/soft centos /bin/bash`