Docker系列:Docker存储管理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker系列:Docker存储管理相关的知识,希望对你有一定的参考价值。

因Docker采用分层文件系统,对容器做的修改都发生在最上层(可写层),这样使得容器可以重复利用。然而,在容器停止时文件系统的最上层(可写层)就消失了,这样容器产生的数据也就无法保存。所以为了持久化存储容器的数据,通常会挂载容器外的存储来保存容器产生的数据,其主要的形式有如下两种方式:
1)数据卷
2)数据(卷)容器

1、数据卷
概念:数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问。

设计目的:数据卷设计的目的,在于数据的永久化,它完全独立于容器的生命周期,因此,Docker不会在容器删除时删除其挂载的数据卷,也不会存在类似的垃圾收集机制,对容器引用的数据卷进行处理。

特点:

  • 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷。
  • 数据卷可以在容器之间共享和重用
  • 可以对数据卷里的内容直接进行修改
  • 数据卷的变化不会影响镜像的更新
  • 卷会一直存在,即使挂载数据卷的容器已经被删除

数据卷的管理:
docker volume COMMAND
    create:创建一个数据卷
    inspect:显示一个或多个数据卷的详细信息
    ls:列出数据卷
    prune:移除所有未使用的数据卷
    rm:删除一个或多个数据卷

# 创建volume卷
[[email protected] ~]# docker volume create myvolume01
myvolume01
[[email protected] ~]# docker volume create myvolume02
myvolume02
# 查看volume卷详细信息
[r[email protected] ~]# docker volume inspect myvolume01
[
    {
        "Driver": "local",``
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/myvolume01/_data",
        "Name": "myvolume01",
        "Options": {},
        "Scope": "local"
    }
]
# 列举volume卷
[[email protected] ~]# docker volume ls
DRIVER              VOLUME NAME
local               myvolume01
local               myvolume02
# 删除volume卷
[[email protected] ~]# docker volume rm myvolume01
myvolume01
[[email protected] ~]# docker volume ls
DRIVER              VOLUME NAME
local               myvolume02
# 移除未使用的volume卷
[[email protected] ~]# 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
[[email protected] ~]# 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目录
[[email protected] ~]# mkdir /tmp/websrvs
[[email protected] ~]# echo "Docker Volume" >> /tmp/websrvs/index.html
#创建一个数据卷容器(因为容器停止后仍可以使用容器的卷,所以仅创建容器即可,可以不启动容器)
[[email protected] ~]# docker create --name centos01 -v /tmp/websrvs:/usr/share/nginx/html:ro centos
bdd70d50bab6c43ab731a1e9921c71121e45199aaf519411089c6a98e2053a69
#将容器卷挂载到另外一个容器中
[[email protected] ~]# docker run -itd --name nginx01 -p 8080:80/tcp --volumes-from centos01 nginx
3c50fa50eb769a0db505d5084a638e7a89b6f5027c994c0aff34dd80b114d76f
#测试是否能正常访问数据
[[email protected] ~]# curl http://localhost:8080
Docker Volume
#进入容器内部查看数据
[[email protected] ~]# docker exec -it nginx01 /bin/bash
[email protected]:/# mount -n |grep "/usr/share/nginx/html"
/dev/mapper/centos-root on /usr/share/nginx/html type ext4 (ro,relatime,data=ordered)
[email protected]:/# cat /usr/share/nginx/html/index.html 
Docker Volume

方法2:共享宿主机数据(目录或文件)

#Docker宿主机上创建一个webroot目录
[[email protected] ~]# mkdir -p /tmp/webroot 
[[email protected] ~]# echo "Docker volume on Guest" >> /tmp/webroot/index.html
#创建一个名为nginx02的容器,挂载webroot目录
[[email protected] ~]# docker run -itd -p 8081:80/tcp --name nginx02 -v /tmp/webroot:/usr/share/nginx/html nginx
08d99f6b920d2a65ad6bdba68c7c0a0602755a25e9d6f62cb25f2ce453f2c962
#创建一个名为nginx03的容器,挂载webroot目录
[[email protected] ~]# docker run -itd -p 8082:80/tcp --name nginx03 -v /tmp/webroot:/usr/share/nginx/html nginx
a05da8b02b5de95f75d1cd166fc21e0fd9bca7031ee79710e11d614b85a1b014
#测试访问web链接,发现访问到的数据是一致的
[[email protected] ~]# curl http://localhost:8081
Docker volume on Guest
[[email protected] ~]# curl http://localhost:8082
Docker volume on Guest
#使用docker exec命令进入docker容器内部,然后尝试修改index.html文件内容
[[email protected] ~]# docker exec -it nginx02 /bin/bash
[email protected]:/# ls /usr/share/nginx/html/
index.html
[email protected]:/# echo "Changed by nginx02." > /usr/share/nginx/html/index.html 
[email protected]:/# cat /usr/share/nginx/html/index.html 
Changed by nginx02.
[email protected]:/# exit
exit
#退出容器后再次访问,发现两个Url得到的数据都发生了改变
[[email protected] ~]# curl http://localhost:8081
Changed by nginx02.
[[email protected] ~]# 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中的符号链接路径
示例:

#拷贝本地文件到容器中
[[email protected] ~]# 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
[[email protected] ~]# echo "Content of test." >> test.html
[[email protected] ~]# docker cp ./test.html nginx03:/usr/share/nginx/html/
[[email protected] ~]# curl http://localhost:8082/test.html
Content of test.
#从容器中拷贝文件到本地
[[email protected] ~]# ls /tmp/websrvs/
index.html
[[email protected] ~]# docker cp -a nginx03:/usr/share/nginx/html/test.html /tmp/websrvs/
[[email protected] ~]# 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
[[email protected] ~]# cat /tmp/websrvs/test.html 
Content of test.
#测试-a和-L参数
[[email protected] ~]# 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
[[email protected] ~]# cat testfiles/index.html    
[[email protected] ~]# cat /usr/share/nginx/html/index.html 
#注意这里testfiles目录下的index.html是一个软连接,链接到本地文件系统中/usr/share/nginx/html/index.html,而文件内容为空
[[email protected] ~]# docker cp -aL testfiles nginx03:/usr/share/nginx/html/
[[email protected] ~]# curl http://localhost:8082/testfiles/   
Changed by nginx02.
#这里获取的实际上是容器内/usr/share/nginx/html/testfiles/index.html的内容
[[email protected] ~]# 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:使用数据卷,将宿主机上的文件或目录挂载到容器中

[[email protected] ~]# docker run -itd --name nginx04 -p 8084:80/tcp -v testfiles:/usr/share/nginx/html nginx
8522678c26427f7e59388549a00cde4e8d462fad9322a337c990436fb9e9e43a
#在本地文件系统中修改,容器内能同步
[[email protected] ~]# echo "Hello, Mr(s). Guest." >> testfiles/welcome.html
[[email protected] ~]# curl http://localhost:8084/welcome.html
Hello, Mr(s). Guest.
#在容器中修改,本地也能同步
[[email protected] ~]# docker exec -d nginx04 rm -f /usr/share/nginx/html/welcome.html
[[email protected] ~]# ls testfiles/welcome.html
ls: cannot access testfiles/welcome.html: No such file or directory

容器的备份和还原
备份:
创建一个需要备份的容器:

[[email protected] ~]# docker run -itd -p 8080:80/tcp -v /usr/share/nginx/html:/usr/share/nginx/html:ro --name websrv01 nginx
ab16bcdcda205c4f610a52bd47d22e32cb7ebbac6618a5027f90f301b973d53d

创建一个用来备份的容器:
[[email protected] ~]# docker run --volumes-from websrv01 -v /opt:/backup --name backupsite01 centos tar zcf /backup/wwwroot.tar.gz /usr/share/nginx/html
生成文件:

[[email protected] ~]# echo "Test file 1." >> /usr/share/nginx/html/test1.html
[[email protected] ~]# echo "Test file 2." >> /usr/share/nginx/html/test2.html
[[email protected] ~]# echo "Test file 3." >> /usr/share/nginx/html/test3.html

查看备份文件:

[[email protected] ~]# 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)上删除文件

[[email protected] ~]# docker exec websrv01 rm -rf /usr/share/nginx/html/*
[[email protected] ~]# 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>
[[email protected] ~]# 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>

创建一个还原用的临时容器,进行还原操作

[[email protected] ~]# docker run --volumes-from websrv01 -v /opt:/backup centos tar zxf /backup/wwwroot.tar.gz -C /usr/share/nginx/html/

验证还原结果

[[email protected] ~]# curl http://localhost:8080/test1.html
Test file 1.
[[email protected] ~]# curl http://localhost:8080/test2.html
Test file 2.
[[email protected] ~]# curl http://localhost:8080/test3.html
Test file 3.

以上是关于Docker系列:Docker存储管理的主要内容,如果未能解决你的问题,请参考以下文章

Swarm系列7--存储介绍

云原生技术分享 | Docker入门系列:初识容器技术

Docker深入浅出系列教程——镜像管理外加视频

Docker深入浅出系列教程——容器管理附加视频

Docker入门与应用系列Docker图形界面管理之Shipyard

docker系列详解docker镜像管理命令