Docker从理论到实践(七)------Docker数据管理

薛经艺
2023-12-01

前言

我们在使用docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据的共享,这必然涉及到容器的数据管理操作。

容器中管理数据主要有两种方式:

  • 数据卷(Data Volumes)
  • 数据卷容器(Data Volumes Dontainers)

接下来,本节主要包括以下内容:

【1】如何在容器内创建数据卷;

【2】如何把本地的目录或文件挂载到容器内的数据卷中;

【3】如何使用数据卷容器在容器和主机、容器和容器之间共享数据,并实现数据的备份和恢复


1、数据卷

数据券是一个可供一个或多个容器使用的特殊目录,它绕过UFS文件系统,是一个从外部挂载在容器内文件系统的目录。可以提供很多有用的特性:

  • 数据券可以在容器之间共享和重用;
  • 对数据券的修改会立马生效;
  • 对数据券的更新,不会影响镜像;
  • 数据券会一直存在,直到没有容器使用。
  • 容器停止运行且被删除时,数据券不受影响,会依然存在于docker宿主机中;

数据券的使用,类似于linux下对目录或文件进行mount操作。


1.1 在容器内创建一个数据券

使用docker run命令时,使用-v标记可以在容器内创建一个数据券。多次使用-v标记可以创建多个数据券。

下面使用training/webapp镜像创建一个web容器,并创建一个数据券挂载到容器的/webapp目录:

docker run -idt -P -v /webapp test/centos:v1.0.1 /bin/bash
#-P为外网到容器的一个映射的IP
#/webapp为创建的数据券
#test/centos:v1.0.1为镜像:标签

执行创建命令后:

[root@master03 /]# docker run -idt -P -v /webapp test/centos:v1.0.1 /bin/bash
0a1d5de1b7b83f00e1fc517216a5a3474b5ccbc14ef1250e719a25f899f89e87
#进入手滑状态运行的容器中
[root@master03 /]# docker attach 0a1d5de1b7b83f00e1fc517216a5a3474b5ccbc14ef1250e719a25f899f89e87
[root@0a1d5de1b7b8 /]# 

在/webapp上面创建你的容器/web1和/webapp目录是共享的,但是对数据券的更新,不会影响镜像。 

[root@master03 /]# docker run -idt -P --name web1 -v /webapp test/centos:v1.0.1 /bin/bash                     
7c25ba62fef63f590cbe1c129ab785375ecb4a65309276e174fb6d4e22970652
[root@master03 /]# docker attach web1
[root@7c25ba62fef6 /]# 

参数说明:

-v:创建一个数据券并且挂载到容器里;

--name:指定容器的名称;

-d:守护状态下运行(daemon)

启动后,使用docker attach命令进入守护状态运行的容器中。


1.2 挂载宿主机目录作为数据券

除此之外,还可以挂载宿主机的一个目录来映射到容器里面作为数据券:

[root@master03 /]# docker run -idt -P --name web2 -v /var/lib/docker/volumes/:/opt/docker/volume/ test/centos:v1.0.1 /bin/bash
d25931d84aef26496cfaaf69232ecf2dc17a38b12311ac45968cd4bb46341c9a
[root@master03 /]# docker attach d25931d84aef26496cfaaf69232ecf2dc17a38b12311ac45968cd4bb46341c9a
[root@d25931d84aef /]# exit
exit
[root@master03 /]# docker attach web2
You cannot attach to a stopped container, start it first
[root@master03 /]# docker ps -a     
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                          PORTS                    NAMES
d25931d84aef        test/centos:v1.0.1         "/bin/bash"              53 seconds ago      Up 1 second                                              web2
7c25ba62fef6        test/centos:v1.0.1         "/bin/bash"              20 minutes ago      Exited (0) About a minute ago                            web1
0a1d5de1b7b8        test/centos:v1.0.1         "/bin/bash"              24 minutes ago      Exited (0) 20 minutes ago                                clever_shaw
1e926a5e946f        test/centos:v1.0.1         "/bin/bash"              3 hours ago         Exited (130) 3 hours ago                                 nifty_edison
e9d4dd65dbe2        training/webapp            "python app.py"          4 hours ago         Up 4 hours                      5000/tcp                 web
becb7857f5d9        registry:latest            "/entrypoint.sh /etc…"   21 hours ago        Up 6 hours                      0.0.0.0:5000->5000/tcp   registry
5517d6d70a09        microsoft/dotnet-samples   "dotnet dotnetapp.dl…"   2 days ago          Exited (0) 2 days ago                                    romantic_goodall
39327f2deca5        centos                     "/bin/bash"              3 days ago          Exited (137) 21 hours ago                                gifted_elbakyan
[root@master03 /]# 
[root@master03 /]# docker attach web2
[root@d25931d84aef /]# 

表示宿主机的目录/var/lib/docker/volumes映射到容器中的/opt/docker/volume目录。

查看一下容器中的/opt/docker/volume目录文件:

#容器的/opt/docker/volume目录
[root@d25931d84aef /]# cd /opt/docker/volume/
[root@d25931d84aef volume]# pwd
/opt/docker/volume
[root@d25931d84aef volume]# ls
0cb1337b9ff9dad2afebb51f7f893e0f6eebc17a15c03f9b2c6f3f8762fbcb80
0d651a78570fa397763ad4bd91959b01c0af55183069c43788d1b00da018efca
12ec97ead61bceb78ec83d52df71cbe2ea6d9ea54c90cfefe6b8f5fa97c32ba6
389bb6f255881a3cb1dc5243895016c9352603899a3b2e7b11cd234775be5f9e
6b101ddbcef53f5cb4d1b101795faf36aaaae4dc809e14743bb8e6cf396b6424
9401d363593a024f39aa1059b496639ee191ac79ba0e6f8e4fc83c0b1d557f62
a716022ffc07596ff4338f43857d09fcd5f57147eb1c5d6d0a38fcd095503d4d
data_1
df53c5509c3154b30294b3324eaf81f7edc7fc57e9461a40ded54a0702d75ad1
metadata.db
[root@d25931d84aef volume]# 

查看一下宿主机中的数据券,我们会发现宿主机的/var/lib/docker/volume目录创建的文件和容器/opt/docker/volume目录下的文件一样。

可以使用命令docker volume list 或者直接进入到宿主机的/var/lib/docker/volume目录下查看:

#宿主机的/var/lib/docker/volumes/目录
[root@master03 /]# cd /var/lib/docker/volumes/
[root@master03 volumes]# ls 
0cb1337b9ff9dad2afebb51f7f893e0f6eebc17a15c03f9b2c6f3f8762fbcb80
0d651a78570fa397763ad4bd91959b01c0af55183069c43788d1b00da018efca
12ec97ead61bceb78ec83d52df71cbe2ea6d9ea54c90cfefe6b8f5fa97c32ba6
389bb6f255881a3cb1dc5243895016c9352603899a3b2e7b11cd234775be5f9e
6b101ddbcef53f5cb4d1b101795faf36aaaae4dc809e14743bb8e6cf396b6424
9401d363593a024f39aa1059b496639ee191ac79ba0e6f8e4fc83c0b1d557f62
a716022ffc07596ff4338f43857d09fcd5f57147eb1c5d6d0a38fcd095503d4d
data_1
df53c5509c3154b30294b3324eaf81f7edc7fc57e9461a40ded54a0702d75ad1
metadata.db
[root@master03 volumes]# 

通过上边的操作,我们可可以挂载宿主机的一个目录来映射到容器里面作为数据券,最终结果就是,宿主机目录下的数据券文件将和容器指定数据券文件目录内容一样。

这里,我们通过docker volume create命令来创建一个别名为data_1和data_2的数据券:

[root@master03 /]# docker volume create --name data_1
data_1 
[root@master03 /]# docker volume inspect  data_1
[
    {
        "CreatedAt": "2019-08-09T00:40:18-04:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/data_1/_data",
        "Name": "data_1",
        "Options": {},
        "Scope": "local"
    }
]
[root@master03 /]# 
[root@master03 /]# docker volume create --name data_2
data_2
[root@master03 /]# docker volume inspect  data_2
[
    {
        "CreatedAt": "2019-08-09T04:54:09-04:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/data_2/_data",
        "Name": "data_2",
        "Options": {},
        "Scope": "local"
    }
]
[root@master03 /]# 

 注意:/var/lib/docker/volume目录为宿主机的数据券目录,而不是容器的数据券目录(/opt/docker/volume)

运行一个容器,挂载data_1数据券到该容器的/data_1目录作为数据券:

docker run -d --name web1 -v data_1:/data_1 nginx

[root@master03 /]# docker run -d --name web3 -v data_1:/opt/docker/volume/data_1 nginx 
60d08f67bdac68a9c7a6f83a4b61241ea13848363775c57377b5a9012cd96b32
[root@master03 /]# docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                         PORTS                    NAMES
60d08f67bdac        nginx                      "nginx -g 'daemon of…"   8 seconds ago       Up 7 seconds                   80/tcp                   web3

1.3 删除数据券

  • docker volume rm <参数:数据卷的VOLUME NAME>

删除数据卷,请注意如果数据卷没有取别名,则名称是64位的全名,不支持模糊匹配,所以在创建数据卷时最好取别名。

  • docker rm -v <参数:容器名称>

随容器删除数据卷,只针对随容器创建时而创建的数据卷。


2、数据卷容器

如果用户需要在容器之间共享一些持续更新的数据,最简单的方式是使用数据券容器

数据券容器实际上就是一个普通的容器,专门为它提供数据券供其他容器挂载。使用方法如下。

【1】首先,利用docker run命令创建一个数据券容器dbdata,并在其中创建一个数据券挂载到/dbdata。

[root@master03 /]# docker run -it -v /dbdata --name dbdata ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7413c47ba209: Pull complete 
0fe7e7cbb2e8: Pull complete 
1d425c982345: Pull complete 
344da5c95cec: Pull complete 
Digest: sha256:d91842ef309155b85a9e5c59566719308fab816b40d376809c39cf1cf4de3c6a
Status: Downloaded newer image for ubuntu:latest

查看新建容器的/dbdata目录:

root@cf958df95262:/# ls
bin  boot  dbdata  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@cf958df95262:/# 

 【2】然后,可以在其他容器中使用--volumes-from来挂载dbdata容器中的数据券。

例如,创建db1和db2两个容器,并从dbdata容器挂载数据券:

docker run -it --volumes-from dbdata --name db1 ubuntu
docker run -it --volumes-from dbdata --name db2 ubuntu

我们使用docker ps -a命令看一下创建出来的容器:

[root@master03 /]# docker ps -a 
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                            PORTS                    NAMES
94d2df4ef3e3        ubuntu                     "/bin/bash"              9 seconds ago       Exited (0) 5 seconds ago                                   db2
fbf1daabef9a        ubuntu                     "/bin/bash"              48 seconds ago      Exited (0) 37 seconds ago                                  db1
cf958df95262        ubuntu                     "/bin/bash"              3 minutes ago       Exited (130) About a minute ago                            dbdata
[root@master03 /]# 

 此时,容器db1和db2容器都挂载同一个数据券得到相同的/dbdata目录。三个容器任何一方在该目录下的写入,其他容器都可以看到。

例如:在dbdata容器中创建一个test文件:

[root@master03 /]# docker attach cf958df95262
root@cf958df95262:/# cd /dbdata/
root@cf958df95262:/dbdata# ls -l
total 0
root@cf958df95262:/dbdata# touch test
root@cf958df95262:/dbdata# ls 
test
root@cf958df95262:/dbdata# 

 在db1容器内查看它:

[root@master03 /]# docker attach db1
root@fbf1daabef9a:/# cd /dbdata/
root@fbf1daabef9a:/dbdata# ls -l
total 0
-rw-r--r-- 1 root root 0 Aug  9 12:06 test
root@fbf1daabef9a:/dbdata# 

 在db2容器内查看test文件:

[root@master03 /]# docker attach db2
root@94d2df4ef3e3:/# cd /dbdata/
root@94d2df4ef3e3:/dbdata# ls 
test
root@94d2df4ef3e3:/dbdata# 

注意:使用--volumes-from参数所挂载数据券的容器自身并不需要保持在运行状态。

 如果删除了挂载的容器(包括dbdata、db1和db2),数据券并不会自动删除。

如果要删除一个数据券,必须在删除最后一个还挂载着它的容器时显式使用docker rm -v命令来指定同时删除关联容器。

使用数据券永琪可以让用户在容器之间自由地升级和移动数据券。


3、利用数据券容器迁移数据

可以利用数据券容器对其中的数据券进行备份、恢复、以实现数据的迁移。

【1】备份

使用下面的命令来备份dbdata数据券容器内的数据券。

docker run --volumes-from dbdata -v ${pwd}:/backup --name worker ubuntu
tar cvf /backup/backup.tar /dbdata

 分析上述命令:

首先利用ubuntu镜像创建了一个容器worker。

使用--volumes-from dbdata参数来让worker容器挂载dbdata容器的数据券(即dbdata数据券);

使用-v${pwd}:/backup参数来挂载本地的当前目录到worker容器的/backup目录。

worker容器启动后,使用了tar cvf /backup/backup.tar /dbdata命令来讲/dbdata下内容备份为容器内的/backup/backup.tar,即宿主机当前目录下的backup.tar。

【2】恢复

如果要恢复数据到一个容器。

首先创建一个带有数据券的容器dbdata2:

docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

 然后,创建另一个新的容器,挂载dbdata2的容器,并使用untar解压备份文件到挂载的容器券中即可:

docker run --volumes-from dbdata2 -v ${pwd}:/backup /backup busybox tar xvf
/backup/backup.tar

 在生产环境中,我们推荐在使用数据券和数据券容器之外,定期将主机的本地数据进行备份,或者使用支持容错的存储系统,包括RAID或分布式文件系统,如GPFS、HDFS


愿你就像早晨八九点钟的太阳,活力十足,永远年轻。

 类似资料: