因Docker采用分层文件系统,对容器做的修改都发生在最上层(可写层),这样使得容器可以重复利用。然而,在容器停止时文件系统的最上层(可写层)就消失了,这样容器产生的数据也就无法保存。所以为了持久化存储容器的数据,通常会挂载容器外的存储来保存容器产生的数据,其主要的形式有如下两种方式:
1)数据卷
2)数据(卷)容器
1、数据卷
概念:数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问。
设计目的:数据卷设计的目的,在于数据的永久化,它完全独立于容器的生命周期,因此,Docker不会在容器删除时删除其挂载的数据卷,也不会存在类似的垃圾收集机制,对容器引用的数据卷进行处理。
特点:
- 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷。
- 数据卷可以在容器之间共享和重用
- 可以对数据卷里的内容直接进行修改
- 数据卷的变化不会影响镜像的更新
- 卷会一直存在,即使挂载数据卷的容器已经被删除
数据卷的管理:
docker volume COMMAND
create:创建一个数据卷
inspect:显示一个或多个数据卷的详细信息
ls:列出数据卷
prune:移除所有未使用的数据卷
rm:删除一个或多个数据卷
# 创建volume卷
[root@centos7 ~]# docker volume create myvolume01
myvolume01
[root@centos7 ~]# docker volume create myvolume02
myvolume02
# 查看volume卷详细信息
[root@centos7 ~]# docker volume inspect myvolume01
[
{
"Driver": "local",``
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/myvolume01/_data",
"Name": "myvolume01",
"Options": {},
"Scope": "local"
}
]
# 列举volume卷
[root@centos7 ~]# docker volume ls
DRIVER VOLUME NAME
local myvolume01
local myvolume02
# 删除volume卷
[root@centos7 ~]# docker volume rm myvolume01
myvolume01
[root@centos7 ~]# docker volume ls
DRIVER VOLUME NAME
local myvolume02
# 移除未使用的volume卷
[root@centos7 ~]# docker volume prune
WARNING! This will remove all volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
myvolume02
Total reclaimed space: 0 B
[root@centos7 ~]# docker volume ls
DRIVER VOLUME NAME
2、数据卷容器
概念:命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷容器。
数据卷容器的特点:
在新创建的容器中挂载数据卷容器后,删除数据卷容器,此时依然能在新创建的容器中访问数据卷。这是因为在创建新的容器时,挂载数据卷容器仅仅是通过数据卷容器将数据卷的信息传递给新的容器,并不会因为数据卷容器的删除而影响数据卷的使用。
即便使用docker rm -v [DOCKER NAME] 指定在删除容器的同时删除数据卷容器,但如果挂载了该数据卷容器的容器处于使用状态,此时该容器依然可以访问数据卷。
数据卷容器的创建:
docker create -v [directory|file] [OPTIONS] IMAGE [COMMAND] [ARG...]
挂载数据卷容器的方法:
docker run --volumes-from [CONTAINER NAME]
Docker容器的数据共享
1)docker容器间共享数据
方法1:使用数据卷容器
#Docker宿主机上创建一个web目录
[root@centos7 ~]# mkdir /tmp/websrvs
[root@centos7 ~]# echo "Docker Volume" >> /tmp/websrvs/index.html
#创建一个数据卷容器(因为容器停止后仍可以使用容器的卷,所以仅创建容器即可,可以不启动容器)
[root@centos7 ~]# docker create --name centos01 -v /tmp/websrvs:/usr/share/nginx/html:ro centos
bdd70d50bab6c43ab731a1e9921c71121e45199aaf519411089c6a98e2053a69
#将容器卷挂载到另外一个容器中
[root@centos7 ~]# docker run -itd --name nginx01 -p 8080:80/tcp --volumes-from centos01 nginx
3c50fa50eb769a0db505d5084a638e7a89b6f5027c994c0aff34dd80b114d76f
#测试是否能正常访问数据
[root@centos7 ~]# curl http://localhost:8080
Docker Volume
#进入容器内部查看数据
[root@centos7 ~]# docker exec -it nginx01 /bin/bash
root@3c50fa50eb76:/# mount -n |grep "\/usr\/share\/nginx\/html"
/dev/mapper/centos-root on /usr/share/nginx/html type ext4 (ro,relatime,data=ordered)
root@3c50fa50eb76:/# cat /usr/share/nginx/html/index.html
Docker Volume
方法2:共享宿主机数据(目录或文件)
#Docker宿主机上创建一个webroot目录
[root@centos7 ~]# mkdir -p /tmp/webroot
[root@centos7 ~]# echo "Docker volume on Guest" >> /tmp/webroot/index.html
#创建一个名为nginx02的容器,挂载webroot目录
[root@centos7 ~]# docker run -itd -p 8081:80/tcp --name nginx02 -v /tmp/webroot:/usr/share/nginx/html nginx
08d99f6b920d2a65ad6bdba68c7c0a0602755a25e9d6f62cb25f2ce453f2c962
#创建一个名为nginx03的容器,挂载webroot目录
[root@centos7 ~]# docker run -itd -p 8082:80/tcp --name nginx03 -v /tmp/webroot:/usr/share/nginx/html nginx
a05da8b02b5de95f75d1cd166fc21e0fd9bca7031ee79710e11d614b85a1b014
#测试访问web链接,发现访问到的数据是一致的
[root@centos7 ~]# curl http://localhost:8081
Docker volume on Guest
[root@centos7 ~]# curl http://localhost:8082
Docker volume on Guest
#使用docker exec命令进入docker容器内部,然后尝试修改index.html文件内容
[root@centos7 ~]# docker exec -it nginx02 /bin/bash
root@08d99f6b920d:/# ls /usr/share/nginx/html/
index.html
root@08d99f6b920d:/# echo "Changed by nginx02." > /usr/share/nginx/html/index.html
root@08d99f6b920d:/# cat /usr/share/nginx/html/index.html
Changed by nginx02.
root@08d99f6b920d:/# exit
exit
#退出容器后再次访问,发现两个Url得到的数据都发生了改变
[root@centos7 ~]# curl http://localhost:8081
Changed by nginx02.
[root@centos7 ~]# curl http://localhost:8082
Changed by nginx02.
注意:
使用docker创建容器的-v选项
-v:物理机文件夹:容器的目录(容器中目录如果不存在,会自动创建,如果存在,会覆盖掉),即将宿主机中的目录挂载到镜像中的目录。
若需要挂载多个目录,可多次采用-v。
2)Docker容器跟宿主机共享数据
方法1:docker cp 在一个容器和本地文件系统之间拷贝文件或目录
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
-a, --archive:归档模式
-L, --follow-link:始终跟踪SRC_PATH中的符号链接路径
示例:
#拷贝本地文件到容器中
[root@centos7 ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a05da8b02b5d nginx "nginx -g ‘daemon ..." 4 hours ago Up 6 seconds 0.0.0.0:8082->80/tcp nginx03
[root@centos7 ~]# echo "Content of test." >> test.html
[root@centos7 ~]# docker cp ./test.html nginx03:/usr/share/nginx/html/
[root@centos7 ~]# curl http://localhost:8082/test.html
Content of test.
#从容器中拷贝文件到本地
[root@centos7 ~]# ls /tmp/websrvs/
index.html
[root@centos7 ~]# docker cp -a nginx03:/usr/share/nginx/html/test.html /tmp/websrvs/
[root@centos7 ~]# ls -l /tmp/websrvs/
total 8
-rw-r--r-- 1 root root 14 Feb 18 14:17 index.html
-rw-r--r-- 1 root root 17 Feb 18 18:58 test.html
[root@centos7 ~]# cat /tmp/websrvs/test.html
Content of test.
#测试-a和-L参数
[root@centos7 ~]# ll testfiles/
total 12
-rw------- 1 root root 1730 Feb 18 19:04 anaconda-ks.cfg
-rw-r--r-- 1 root root 38 Feb 9 02:15 Dockerfile
lrwxrwxrwx 1 root root 32 Feb 18 19:05 index.html -> /usr/share/nginx/html/index.html
-rw-r--r-- 1 root root 17 Feb 18 18:58 test.html
[root@centos7 ~]# cat testfiles/index.html
[root@centos7 ~]# cat /usr/share/nginx/html/index.html
#注意这里testfiles目录下的index.html是一个软连接,链接到本地文件系统中/usr/share/nginx/html/index.html,而文件内容为空
[root@centos7 ~]# docker cp -aL testfiles nginx03:/usr/share/nginx/html/
[root@centos7 ~]# curl http://localhost:8082/testfiles/
Changed by nginx02.
#这里获取的实际上是容器内/usr/share/nginx/html/testfiles/index.html的内容
[root@centos7 ~]# curl http://localhost:8082/
Changed by nginx02.
#这里获取的是容器内/usr/share/nginx/html/index.html的内容
#因为访问两个地址的结果一致,说明-L参数将符号链接完全拷贝过去,容器内的/usr/share/nginx/html/testfiles/index.html 仍然指向 /usr/local/nginx/html/index.html,而容器内的 /usr/local/nginx/html/index.html文件是有内容的,因而2次访问的结果都是有内容返回的。
方法2:使用数据卷,将宿主机上的文件或目录挂载到容器中
[root@centos7 ~]# docker run -itd --name nginx04 -p 8084:80/tcp -v testfiles:/usr/share/nginx/html nginx
8522678c26427f7e59388549a00cde4e8d462fad9322a337c990436fb9e9e43a
#在本地文件系统中修改,容器内能同步
[root@centos7 ~]# echo "Hello, Mr(s). Guest." >> testfiles/welcome.html
[root@centos7 ~]# curl http://localhost:8084/welcome.html
Hello, Mr(s). Guest.
#在容器中修改,本地也能同步
[root@centos7 ~]# docker exec -d nginx04 rm -f /usr/share/nginx/html/welcome.html
[root@centos7 ~]# ls testfiles/welcome.html
ls: cannot access testfiles/welcome.html: No such file or directory
容器的备份和还原
备份:
创建一个需要备份的容器:
[root@centos7 ~]# docker run -itd -p 8080:80/tcp -v /usr/share/nginx/html:/usr/share/nginx/html:ro --name websrv01 nginx
ab16bcdcda205c4f610a52bd47d22e32cb7ebbac6618a5027f90f301b973d53d
创建一个用来备份的容器:[root@centos7 ~]# docker run --volumes-from websrv01 -v /opt:/backup --name backupsite01 centos tar zcf /backup/wwwroot.tar.gz /usr/share/nginx/html
生成文件:
[root@centos7 ~]# echo "Test file 1." >> /usr/share/nginx/html/test1.html
[root@centos7 ~]# echo "Test file 2." >> /usr/share/nginx/html/test2.html
[root@centos7 ~]# echo "Test file 3." >> /usr/share/nginx/html/test3.html
查看备份文件:
[root@centos7 ~]# tar -ztf /opt/wwwroot.tar.gz
usr/share/nginx/html/
usr/share/nginx/html/index.html
usr/share/nginx/html/test2.html
usr/share/nginx/html/test3.html
usr/share/nginx/html/test1.html
还原:
到要还原的容器(websrv01)上删除文件
[root@centos7 ~]# docker exec websrv01 rm -rf /usr/share/nginx/html/*
[root@centos7 ~]# curl http://localhost:8080/test1.html
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.15.8</center>
</body>
</html>
[root@centos7 ~]# curl http://localhost:8080/test2.html
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.15.8</center>
</body>
</html>
创建一个还原用的临时容器,进行还原操作
[root@centos7 ~]# docker run --volumes-from websrv01 -v /opt:/backup centos tar zxf /backup/wwwroot.tar.gz -C /usr/share/nginx/html/
验证还原结果
[root@centos7 ~]# curl http://localhost:8080/test1.html
Test file 1.
[root@centos7 ~]# curl http://localhost:8080/test2.html
Test file 2.
[root@centos7 ~]# curl http://localhost:8080/test3.html
Test file 3.
原文地址:http://blog.51cto.com/jerry12356/2351505