容器云系列之Docker数据卷管理

本文简要介绍了Docker容器对数据卷管理。


1、Docker数据卷管理

数据卷是Docker容器保存数据的方式,跟bind mounts方式相比,有以下优势:

  1. 数据卷更容易备份迁移
  2. 使用Docker CLI或者Docker API对数据卷进行管理
  3. 数据卷可以在多个容器间共享和复用
  4. Volumes driver可以将卷内容存储在远端主机上
  5. 可以使用Docker填充新的数据卷内容
  6. 数据卷内容存在Docker容器之外,并不会增加容器本身大小

在这里插入图片描述

1.1 创建和管理卷

1)创建卷

[root@tango-01 ~]# docker volume create my-volume
my-volume

2)List卷

[root@tango-01 ~]# docker volume ls
DRIVER              VOLUME NAME
local               4a77c195a70ff39c151ad75367d41f7db1f48de06e0ebb0333189724ca6c389a
local               73cca56105d152363bf63789bb3093443ec239559029caffc66da1a78257f200
local               548de7d0ba3d0a8c85a4b25e1234ba1b2a5891068a3062858825389a3ee4fc42
local               my-volume

3)Inspect volume查看卷详细信息

[root@tango-01 ~]# docker volume inspect my-volume
[
    {
        "CreatedAt": "2020-10-06T20:25:50+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
        "Name": "my-volume",
        "Options": {},
        "Scope": "local"
    }
]

4)Remove volume

[root@tango-01 ~]#  docker volume rm my-volume
my-volume

5)使用-v选项添加一个数据卷

[root@tango-01 docker]# docker run -d  --name voltest   -v my-vol1:/data nginx:latest
966f73c1e518adfd115b5bb3321effc9b5692a10a64a2dbf992e533465dc516c
[root@tango-01 docker]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
966f73c1e518        nginx:latest        "/docker-entrypoint.…"   6 seconds ago       Up 5 seconds        80/tcp              voltest
[root@tango-01 docker]# docker volume ls
DRIVER              VOLUME NAME
local               4a77c195a70ff39c151ad75367d41f7db1f48de06e0ebb0333189724ca6c389a
local               73cca56105d152363bf63789bb3093443ec239559029caffc66da1a78257f200
local               548de7d0ba3d0a8c85a4b25e1234ba1b2a5891068a3062858825389a3ee4fc42
local               my-vol1

创建数据卷绑定到到新建容器,新建容器中会创建/data数据卷,如果卷不存在,Docker会创建一个新的volume。

>>挂载时创建卷<<

1)挂载卷

[root@tango-01 docker]# docker run -d -p 80:80 -v /data:/usr/share/nginx/html nginx:latest
66bc9c834237cc2f0bf47e63a7f3a2eb0ce51a6689309a6f740dc268403a44ff
[root@tango-01 docker]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
66bc9c834237        nginx:latest        "/docker-entrypoint.…"   6 seconds ago       Up 6 seconds        0.0.0.0:80->80/tcp   mystifying_banzai

容器内站点目录: /usr/share/nginx/html

2)在宿主机写入数据,查看

[root@tango-01 /]# echo "hello tango" >/data/index.html
[root@tango-01 /]# curl 192.168.112.10
hello tango

3)设置共享卷,使用同一个卷启动一个新的容器

[root@tango-01 /]# docker run -d -p 8080:80 -v /data:/usr/share/nginx/html nginx:latest
b2cb700cd9937674e6d08326ede94932855d59d327c90427ba027903d9c90e61
[root@tango-01 /]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                  NAMES
b2cb700cd993        nginx:latest        "/docker-entrypoint.…"   6 seconds ago        Up 4 seconds        0.0.0.0:8080->80/tcp   charming_wright
66bc9c834237        nginx:latest        "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp     mystifying_banzai
[root@tango-01 /]# curl 192.168.112.10:8080
hello tango

4)查看卷列表

[root@tango-01 /]# docker volume ls
DRIVER              VOLUME NAME
local               4a77c195a70ff39c151ad75367d41f7db1f48de06e0ebb0333189724ca6c389a
local               73cca56105d152363bf63789bb3093443ec239559029caffc66da1a78257f200
local               548de7d0ba3d0a8c85a4b25e1234ba1b2a5891068a3062858825389a3ee4fc42
local               my-vol1
>>创建卷后挂载<<

1)使用卷创建

[root@tango-01 /]# docker run -d -p 9080:80 -v my-vol1:/usr/share/nginx/html nginx:latest
43be86f4ec307e509c36d4145de3cd874c7d8adacff53e32f2a994953b86f7a0

2)宿主机测试

[root@tango-01 /]# echo 'hello tango' > /var/lib/docker/volumes/my-vol1/_data/index.html
[root@tango-01 /]# curl 192.168.112.10:9080
hello tango

3)设置卷

[root@tango-01 /]# docker run  -d  -P  --volumes-from 43be86f4ec30 nginx:latest 
5acebbac45d74890819ab36aa38241f2d5fcd0673d7624bf4a55894d3e11efcf
[root@tango-01 /]# 
[root@tango-01 /]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
5acebbac45d7        nginx:latest        "/docker-entrypoint.…"   5 seconds ago       Up 4 seconds        0.0.0.0:32768->80/tcp   upbeat_einstein
43be86f4ec30        nginx:latest        "/docker-entrypoint.…"   9 minutes ago       Up 8 minutes        0.0.0.0:9080->80/tcp    elated_lederberg
b2cb700cd993        nginx:latest        "/docker-entrypoint.…"   15 minutes ago      Up 14 minutes       0.0.0.0:8080->80/tcp    charming_wright
66bc9c834237        nginx:latest        "/docker-entrypoint.…"   16 minutes ago      Up 16 minutes       0.0.0.0:80->80/tcp      mystifying_banzai
[root@tango-01 /]# curl 192.168.112.10:32768
hello tango
1.2 备份、恢复或迁移数据卷

1)数据卷备份

[root@tango-01 /]# docker run -v /testdata --name voltest ubuntu /bin/bash
[root@tango-01 /]# docker run --rm --volumes-from voltest -v $(pwd):/backup ubuntu tar cvf /backup/test.tar /testdata
tar: Removing leading `/' from member names
/testdata/

启动一个新的容器并且从voltest容器中挂载卷,然后挂载当前目录到容器中为backup,并备份test卷中所有的数据为test.tar,执行完成之后删除容器–rm,此时备份就在当前的目录下,名为test.tar。

注意:后面的/data是数据卷的目录路径(即数据卷创建时在容器里的路径)

2)数据卷恢复或迁移

可以恢复给同一个容器或者另外的容器,新建容器并解压备份文件到新的容器数据卷

[root@tango-01 /]# docker run -v /testdata --name voltest1 ubuntu /bin/bash
[root@tango-01 /]# docker run --rm --volumes-from voltest1 -v $(pwd):/backup ubuntu bash -c "cd /testdata && tar xvf /backup/test.tar --strip 1"

恢复之前的文件到新建卷中,执行完后自动删除容器

>>数据卷备份恢复操作实战<<

1)先创建一个容器voltest,包含两个数据卷/var/volume1和/var/volume2(这两个目录是在容器里的数据卷路径)

[root@tango-01 /]# docker run -t -i -v /var/volume1 -v /var/volume2 --name voltest ubuntu /bin/bash
root@881631b3f8c5:

根据Docker的数据持久化之数据卷容器可知,上面创建的voltest数据卷容器挂载了/var/volume1和/var/volume2两个目录。

2)在数据卷里写些数据,以供测试

root@881631b3f8c5:/# cd /var/volume1
root@881631b3f8c5:/var/volume1# echo "test1" > test1
root@881631b3f8c5:/var/volume1# echo "test11" > test11
root@881631b3f8c5:/var/volume1# echo "test111" > test111
root@881631b3f8c5:/var/volume1# ls
test1  test11  test111
root@881631b3f8c5:/var/volume1# cd /var/volume2
root@881631b3f8c5:/var/volume2# echo "test2" > test2
root@881631b3f8c5:/var/volume2# echo "test22" > test22
root@881631b3f8c5:/var/volume2# echo "test222" > test222
root@881631b3f8c5:/var/volume2# ls
test2  test22  test222

3)进行数据卷的备份操作

为了利用数据卷容器备份,使用–volumes-from标记来创建一个加载voltest容器卷的容器,并从主机挂载当前目录到容器的/backup目录。并备份voltest卷中的数据,执行完成之后删除容器–rm,此时备份就在当前的目录下了。

a) 备份voltest容器中的/var/volume1数据卷数据

[root@tango-01 /]# docker run -i -t --volumes-from voltest -v $(pwd):/backup ubuntu tar cvf /backup/backup1.tar /var/volume1
tar: Removing leading `/' from member names
/var/volume1/
/var/volume1/test1
/var/volume1/test11
/var/volume1/test111

b) 备份voltest容器中的/var/volume2数据卷数据

[root@tango-01 /]# docker run -i -t --volumes-from voltest -v $(pwd):/backup ubuntu tar cvf /backup/backup2.tar /var/volume2
tar: Removing leading `/' from member names
/var/volume2/
/var/volume2/test2
/var/volume2/test22
/var/volume2/test222

c) 备份voltest容器中的/var/volume1和/var/volume2数据卷数据

[root@tango-01 /]# docker run -i -t --volumes-from voltest -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /var/volume1 /var/volume2
tar: Removing leading `/' from member names
/var/volume1/
/var/volume1/test1
tar: Removing leading `/' from hard link targets
/var/volume1/test11
/var/volume1/test111
/var/volume2/
/var/volume2/test2
/var/volume2/test22
/var/volume2/test222
[root@tango-01 /]# ls -l
total 68
-rw-r--r--    1 root root 10240 Oct  6 22:04 backup1.tar
-rw-r--r--    1 root root 10240 Oct  6 22:05 backup2.tar
-rw-r--r--    1 root root 10240 Oct  6 22:06 backup.tar

这样,数据卷容器中的数据就备份完成了

4)恢复数据给同一个容器

a) 为了测试效果,先删除数据卷

[root@tango-01 /]# docker start voltest
voltest
[root@tango-01 /]# docker attach voltest
root@881631b3f8c5:/# ls /var/volume1
test1  test11  test111
root@881631b3f8c5:/# ls /var/volume2
test2  test22  test222
root@881631b3f8c5:/# rm -rf /var/volume1
rm: cannot remove '/var/volume1': Device or resource busy
root@881631b3f8c5:/# rm -rf /var/volume2
rm: cannot remove '/var/volume2': Device or resource busy
root@881631b3f8c5:/# ls /var/volume1    
root@881631b3f8c5:/# ls /var/volume2

b) 进行数据卷恢复,恢复数据卷中的所有数据:

[root@tango-01 /]# docker run --rm --volumes-from voltest -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar -C /
var/volume1/
var/volume1/test1
var/volume1/test11
var/volume1/test111
var/volume2/
var/volume2/test2
var/volume2/test22
var/volume2/test222

注意-C后面的路径,这个路径表示将数据恢复到容器里的路径。命令中用"/",即表示将backup.tar中的数据解压到容器的/路径下。后面跟什么路径,就解压到这个路径下,因此这里用"/"。

c) 再次到容器里查看,发现数据卷里的数据已经恢复了

[root@tango-01 /]# docker start voltest
voltest
[root@tango-01 /]# docker attach voltest
root@881631b3f8c5:/# ls /var/volume1
test1  test11  test111
root@881631b3f8c5:/# ls /var/volume2
test2  test22  test222

5)恢复数据给另外的容器,新建容器并解压备份文件到新的容器数据卷

即新建一个容器voltest1,将上面备份的数据卷数据恢复到这个新容器里

[root@tango-01 /]# docker run -t -i -v /var/volume1 -v /var/volume2 --name voltest1 ubuntu /bin/bash
root@7acb459cbe1c:/# ls /var/volume1
root@7acb459cbe1c:/# ls /var/volume2

恢复数据到新的容器voltest1中:

[root@tango-01 /]# docker run --rm --volumes-from voltest1 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar -C /
var/volume1/
var/volume1/test1
var/volume1/test11
var/volume1/test111
var/volume2/
var/volume2/test2
var/volume2/test22
var/volume2/test222
[root@tango-01 /]# docker start voltest1
voltest1
[root@tango-01 /]# docker attach voltest1
root@7acb459cbe1c:/# ls /var/volume1
test1  test11  test111
root@7acb459cbe1c:/# ls /var/volume2
test2  test22  test222

注:新容器创建时挂载的数据卷路径最好是和之前备份的数据卷路径一致

6)新建容器挂载的数据卷只是备份数据卷的一部分,那么恢复的时候也只是恢复一部分数据。如下,新容器创建时只挂载/var/volume1

[root@tango-01 /]# docker run -t -i -v /var/volume1 --name voltest2 ubuntu /bin/bash
root@e2c453c81390:/# ls /var/volume1
root@e2c453c81390:/# ls /var/volume2
ls: cannot access '/var/volume2': No such file or directory

恢复数据到新的容器voltest2中:

[root@tango-01 /]# docker run --rm --volumes-from voltest2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar -C /
var/volume1/
var/volume1/test1
var/volume1/test11
var/volume1/test111
var/volume2/
var/volume2/test2
var/volume2/test22
var/volume2/test222
root@e2c453c81390:/# ls /var/volume1
test1  test11  test111

查看容器,发现只恢复了/var/volume1的数据,/var/volume2数据没有恢复,因为没有容器创建时没有挂载这个。

7)如果新容器创建时挂载的数据卷目录跟之前备份的路径不一致

[root@tango-01 /]# docker run -t -i -v /var/volume3 --name voltest3 ubuntu /bin/bash
root@06bfbfc830a7:/# ls /var/volume3

如果解压时-C后面跟的路径不是容器挂载的容器,那么数据恢复不了,如下

[root@tango-01 /]# docker run --rm --volumes-from voltest3 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar -C /
var/volume1/
var/volume1/test1
var/volume1/test11
var/volume1/test111
var/volume2/
var/volume2/test2
var/volume2/test22
var/volume2/test222

发现容器内数据没有恢复

root@06bfbfc830a7:/# ls /var/volume3
root@06bfbfc830a7:/#

但是如果解压时-C后面跟的是容器挂载的路径,数据就能正常恢复

[root@tango-01 /]# docker run --rm --volumes-from voltest3 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar -C /var/volume3
var/volume1/
var/volume1/test1
var/volume1/test11
var/volume1/test111
var/volume2/
var/volume2/test2
var/volume2/test22
var/volume2/test222

发现容器内数据已经恢复了

root@06bfbfc830a7:/# ls /var/volume3
var
root@06bfbfc830a7:/# ls /var/volume3/var
volume1  volume2
root@06bfbfc830a7:/# ls /var/volume3/var/volume1
test1  test11  test111
root@06bfbfc830a7:/# ls /var/volume3/var/volume2
test2  test22  test222
root@06bfbfc830a7:/#
2、Docker容器资源限制
2.1 Namespace资源隔离

Docker使用Linux namespace技术实现容器间的资源隔离
在这里插入图片描述

>>以PID namespace为例<<

1)启动一个容器

[root@tango-01 /]# docker run -it  --name pidtest ubuntu /bin/bash

2)查看容器中的进程id(可以看到/bin/sh的pid=1)

root@e9fcfb4c6f17:/# ps
   PID TTY          TIME CMD
     1 pts/0    00:00:00 bash
     8 pts/0    00:00:00 ps

3)查看宿主机中的该/bin/sh的进程id

[root@tango-01 /]# ps -ef|grep ubuntu
root       3079   1671  0 14:48 pts/0    00:00:00 docker run -it --name pidtest ubuntu /bin/bash
root       3146   2387  0 14:49 pts/1    00:00:00 grep --color=auto ubuntu

可以看到,在Docker里最开始执行的/bin/sh,就是这个容器内部的第1号进程(PID=1),而在宿主机上看到它的PID=3709。这就意味着,前面执行的/bin/sh,已经被Docker隔离在了一个跟宿主机完全不同的世界当中。这就是Docker在启动一个容器(创建一个进程)时使用了PID namespace


参考资料

  1. https://docs.docker.com/storage/volumes/
  2. https://www.cnblogs.com/kevingrace/p/6238195.html
  3. https://www.cnblogs.com/zhuochong/p/9728383.html
  4. https://blog.csdn.net/songcf_faith/article/details/82749011
  5. https://blog.csdn.net/songcf_faith/article/details/82748987

转载请注明原文地址:https://blog.csdn.net/solihawk/article/details/121220602
文章会同步在公众号“牧羊人的方向”更新,感兴趣的可以关注公众号,谢谢!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值