5.Docker数据管理

文章目录

Docker数据管理

在生产环境中使用 Docker涉及容器的数据管理操作,需要对数据进行持久化或者需要在多个容器之间进行数据共享。

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

  • 数据卷 (Data Volumes): 容器内数据直接映射到本地主机环境;

    在容器内创建数据卷, 并且把本地的目录或文件挂载到容器内的数据卷中。

  • 数据卷容器 (Data Volume Containers): 使用特定容器维护数据卷。

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

1、数据卷

数据卷(Data Volumes)是一个可供容器使用的特殊目录映射进容器,它将主机操作系统目录直接类似于Linux中的mount行为。

数据卷特性:

  • 数据卷可以在容器之间共享和重用, 容器间传递数据将变得高效与方便;
  • 对数据卷内数据的修改会立马生效, 无论是容器内操作还是本地操作;
  • 对数据卷的更新不会影响镜像, 解耦开应用和数据;
  • 卷会一直存在, 直到没有容器使用, 可以安全地卸载它。

1.1、创建数据卷

volume子命令管理数据卷

bash 复制代码
[root@localhost ~]# docker volume create -d local test
test
#查看/var/lib/docker/volumes路径下,会发现所创建的数据卷位置
[root@localhost ~]# ls -l /var/lib/docker/volumes/
drwx-----x. 3 root root     19 5月   6 23:03 test

docker volume还支持inspect(查看详细信息)、ls (列出已有数据卷)、prune(清理无用数据卷)、rm(删除数据卷)等。

bash 复制代码
[root@localhost ~]# docker volume inspect test
[
    {
        "CreatedAt": "2024-05-06T23:03:37-04:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/test/_data",
        "Name": "test",
        "Options": null,
        "Scope": "local"
    }
]
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     3c5f45922be6ba271bd6f40bfb160d55d6552e46a2b0155ed6c31fee47dbf430
local     baf0e871e0586fdc374d0451354c488a413270ccc8cb4e7c53a47510c30b01ad
local     test
[root@localhost ~]# docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B

1.2、绑定数据卷

在创建容器时将主机本地的任意路径挂载到容器内作为数据卷,这种形式创建的数据卷称为绑定数据卷。

docker [container] run命令可以使用-mount选项来使用数据卷。

-mount选项支持三种类型的数据卷:

  • volume: 普通数据卷,映射到主机 /var/lib/docker/volumes路径下;
  • bind: 绑定数据卷, 映射到主机指定路径下;
  • tmpfs: 临时数据卷,只存在于内存中。

举例:使用 training/webapp镜像创建一个Web容器,并创建一个数据卷挂载到容器的/opt/webapp目录。

bash 复制代码
[root@localhost ~]$ mkdir /webapp
[root@localhost ~]$ docker run -d -it -P --name web --mount type=bind,source=/webapp,destination=/opt/webapp ubuntu /bin/bash
#等价于使用旧的 -v标记可以在容器内创建一个数据卷
$ docker run -d -it -P --name web -v /webapp:/opt/webapp ubuntu /bin/bash
#测试
[root@localhost ~]# cd /webapp/
[root@localhost webapp]# touch a
[root@localhost webapp]# ls
a  
[root@localhost ~]# docker exec -it adc2b32202cd /bin/bash
root@adc2b32202cd:/# cd /opt/webapp/
root@adc2b32202cd:/opt/webapp# ls
a

用户可以放置一些程序或数据到本地目录中实时进行更新,然后在容器内运行和使用。本地目录的路径必须是绝对路径,容器内路径可以为相对路径。如果目录不存在,Docker会自动创建。

查看数据卷是否挂载成功:

bash 复制代码
docker inspect 容器名称

Docker挂载数据卷的默认权限是读写(rw), 用户也可以通过ro指定为只读,容器内对所挂载数据卷内的数据就无法修改。

bash 复制代码
$ docker run -d -it -P --name web -v /webapp:/opt/webapp:ro ubuntu /bin/bash

直接挂载一个文件到容器,使用文件编辑工具,包括 vi或者sed --in-place 的时候,可能会造成文件 inode的改变。从Docker 1. 1 .0起,这会导致报错误信息。所以推荐的方式是直接挂载文件所 在的目录到容器内。

💡Docker挂载主机目录访问如果出现cannot open directory .: Permission denied

解决办法:在挂载目录后多加一个--privileged=true参数即可。

原因是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,在SELinux里面挂载目录被禁止掉了,如果要开启,我们一般使用--privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

2、数据卷容器

数据卷容器是专门提供数据卷给其他容器挂载的容器。如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。

  1. 创建一个数据卷容器dbdata, 并在其中创建一个数据卷挂载到/dbdata

    bash 复制代码
    [root@localhost ~]# mkdir /dbdata
    [root@localhost ~]# docker run -it -v /dbdata --name dbdata ubuntu
    root@529ee7fec788:/# ls
    bin  boot  dbdata  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
  2. 可以在其他容器中使用--volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器并从dbdata容器挂载数据卷。

    bash 复制代码
    [root@localhost ~]# docker run -it -d --volumes-from dbdata --name db1 ubuntu
    63241c4a05903f0dad1a13ded4d4390b2978ab801bb999773d8459f2e3b786e6
    [root@localhost ~]# docker run -it -d --volumes-from dbdata --name db2 ubuntu
    51cc6dadb57707bfb39e0a8d9c3e79d7bcde52a82c4fb1e971c51898c5681079
    
    [root@localhost ~]# docker exec -it db1 /bin/bash
    root@63241c4a0590:/# ls
    bin  boot  dbdata  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

    在数据卷容器dbdata中挂载目录创建文件后,在db1和db2中可以看到和使用。

🔔可以多次使用--volumes-from参数来从多个容器挂载多个数据卷,还可以从其他已经挂载了容器卷的容器来挂载数据卷。使用--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态。

如果删除了挂载的容器(包括dbdata、db1和db2), 数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用docker rm -v命令来指定同时删除关联的容器。

bash 复制代码
[root@localhost ~]# docker run -it -d --name db3 --volumes-from db1 ubuntu
f739ab152a712eeb3dda3f079c490d06338bfb8f89137f7abc3ccb6f110e0f0b
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                   CREATED         STATUS          PORTS                                       NAMES
f739ab152a71   ubuntu       "bash"                    2 seconds ago   Up 2 seconds                                                db3
51cc6dadb577   ubuntu       "bash"                    2 hours ago     Up 52 seconds                                               db2
63241c4a0590   ubuntu       "bash"                    2 hours ago     Up 53 seconds                                               db1
529ee7fec788   ubuntu       "bash"                    3 hours ago     Up 58 seconds                                               dbdata
[root@localhost ~]# 
[root@localhost ~]# docker exec -it db3 /bin/bash
root@f739ab152a71:/# 
root@f739ab152a71:/# ls
bin  boot  dbdata  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@f739ab152a71:/# exit
exit

[root@localhost ~]# docker rm -v db1 db3
Error response from daemon: cannot remove container "/db1": container is running: stop the container before removing or force remove
Error response from daemon: cannot remove container "/db3": container is running: stop the container before removing or force remove
[root@localhost ~]# docker stop db1
db1
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                   CREATED              STATUS              PORTS                                       NAMES
f739ab152a71   ubuntu       "bash"                    About a minute ago   Up About a minute                                               db3
51cc6dadb577   ubuntu       "bash"                    2 hours ago          Up 2 minutes                                                    db2
529ee7fec788   ubuntu       "bash"                    3 hours ago          Up 2 minutes                                                    dbdata
[root@localhost ~]# docker stop db3
db3
[root@localhost ~]# docker rm -v db1 db3
db1
db3
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                   CREATED       STATUS          PORTS                                       NAMES
51cc6dadb577   ubuntu       "bash"                    2 hours ago   Up 2 minutes                                                db2
529ee7fec788   ubuntu       "bash"                    3 hours ago   Up 2 minutes                                                dbdata

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

3.1、备份

备份dbdata数据卷容器内的数据卷

bash 复制代码
docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar
cvf /backup/backup.tar /dbdata

理解:

  1. 专门启动一个worker容器,将当前目录映射到容器的/backup目录下;
  2. 使用--volumes-from dbdata参数来让worker容器挂载dbdata容器的数据卷;
  3. 将worker容器中的/dbdata目录压缩存储至backup目录下;
  4. 此时查看宿主机本地目录,可以查看到压缩包。

3.2、恢复

1.创建一个带有数据卷的容器dbdata2

bash 复制代码
$ docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

2.创建另一个新的容器, 挂载dbdata2的容器, 并使用untar解压备份文件到所挂载的容器卷中

bash 复制代码
$ docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar -C /dbdata
#等价于
$ docker run --mount source=dbdata2,target=/dbd --mount type=bind,source=$(pwd),target=/backup busybox tar xvf /backup/backup.tar -C /dbd

总结

​ 数据卷机制为数据管理提供了方便的操作支持 。通过数据卷和数据卷容器对容器内的数据进行共享、备份和恢复等操作, 这些机制即使容器在运行中出现故障,用户也不必担心数据发生丢失, 只需要快速地重新创建容器即可。

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

​ 另外, 有些时候不希望将数据保存在宿主机或容器中, 还可以使用 tmpfs类型的数据卷, 其中数据只存在内存中, 容器退出后自动删除。

相关推荐
闲云自留地2 小时前
K8s 的记忆大脑!ETCD 集群部署、etcdctl 命令与备份恢复全通关
容器·kubernetes·etcd
讯捷蓝达3 小时前
戴尔R720xd服务器卡死在 “Configuring Memory...Done“,换了内存还是卡?问题根本不在内存
运维·服务器
爱和冰阔落5 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
lisanmengmeng6 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器
Android系统攻城狮6 小时前
Linux FFmpeg深度解析之av_write_frame调用流程与实战(三十三)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频
上火的金鱼妹6 小时前
k8s生产实际问题排查(网关,数据库读写等)
运维·服务器
孙克旭_7 小时前
k8s基础组件与创建资源
运维·docker·容器·kubernetes
孙克旭_7 小时前
云原生基础之Containerd容器运行时
运维·云原生
分布式存储与RustFS7 小时前
RustFS 自建对象存储实战目录:110 篇按场景分类(持续更新)
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
无忧_wy7 小时前
MoneyPrinterTurbo 自动化视频生成实战指南
运维·人工智能·自动化·音视频