docker之数据管理

        在生产环境中使用docker,往往需要对数据进行持久化操作,或者需要再多个容器之间进行数据共享,这就涉及到了容器中管理数据的两种方式:数据卷(Data Volumes)和数据卷容器(Data Volumes Containers)

1.数据卷(Data Volumes)

        将主机操作系统目录直接映射到容器目录,类似与linux里面的mount行为

        数据卷的特性:

                1.数据卷可以在容器之间共享和重用,容器间传递数据将变得更高效和方便

                2.对数据卷内数据的修改会立马生效,无论是从容器还是从linux本地操作

                3.对数据卷的更新不会影响到镜像,将应用和数据解耦出来

                4.卷会一直存在,知道没有容器使用后,您才可以卸载掉改盘

1.1 创建数据卷

docker volume create -d local test 

[root@k8s-master system]# docker volume create -d local test
test
[root@k8s-master system]# ls -la /var/lib/docker/volumes/test/
total 4
drwx-----x.  3 root root   19 Sep 25 17:08 .
drwx-----x. 22 root root 4096 Sep 25 17:08 ..
drwxr-xr-x.  2 root root    6 Sep 25 17:08 _data

1.2 绑定数据卷

当我们在run一个容器的时候,可以将本地路径挂载到容器内部作为数据卷,这种形式创建的数据卷成为绑定数据卷,一般用-mount选项来使用数据卷。-mount支持三种类型的数据卷,包括:

1.volume:普通数据卷,映射到/var/lib/docker/volumes路径下

2.bind:绑定数据卷,映射到主机指定路径下

3.tmpfs:临时数据卷,只存在于内存中

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

docker run -d -P --name web --mount type=bind,source=/webapp,destination=/opt/webapp training/webapp python app.py

#将之前的harbor仓库地址注销掉,使用官方仓库
[root@k8s-master ~]# mv /etc/docker/daemon.json /etc/docker/daemon.json.bak
[root@k8s-master ~]# systemctl restart docker.service
[root@k8s-master opt]# mkdir -p /webapp
[root@k8s-master ~]# docker run -d -P --name web --mount type=bind,source=/webapp,destination=/opt/webapp training/webapp python app.py
Unable to find image 'training/webapp:latest' locally
latest: Pulling from training/webapp
[DEPRECATION NOTICE] Docker Image Format v1, and Docker Image manifest version 2, schema 1 support will be removed in an upcoming release. Suggest the author of docker.io/training/webapp:latest to upgrade the image to the OCI Format, or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/
e190868d63f8: Pull complete 
909cd34c6fd7: Pull complete 
0b9bfabab7c1: Pull complete 
a3ed95caeb02: Pull complete 
10bbbc0fc0ff: Pull complete 
fca59b508e9f: Pull complete 
e7ae2541b15b: Pull complete 
9dd97ef58ce9: Pull complete 
a4c1b0cb7af7: Pull complete 
Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d
Status: Downloaded newer image for training/webapp:latest
c97774581f5e919bbdb910aad04a5e5a1fdc7804eed811eaf105ca28fc737136

上面的命令等同于:

docker run -d -P --name wb -v /webapp:/opt/webapp training/webapp python app.py

Docker 挂载数据卷默认是读写权限(rw),指定为只读(ro)的命令为:

docker run -d -P --name wb -v /webapp:/opt/webapp training/webapp:ro python app.py

容器无法对/webapp目录也就是/opt/webapp目录进行修改了

tips:如果直接挂载文件到容器时,用vi或者sed对文件进行修改会改变文件inode,我们推荐是直接挂载文件所在的目录到容器,这里我们可以做个小实验来看看

#1.创建test文件
[root@k8s-master ~]# echo 'hello docker' >test.txt
[root@k8s-master ~]# chmod 644 test.txt 
#2.启动一个容器挂载/root/test.txt文件
[root@k8s-master ~]# docker run -it --rm -v /root/test.txt:/root/test.txt ubuntu
root@7055764ca5bf:/# 
#3.容器里查看test.txt文件的inode
root@7055764ca5bf:~# stat test.txt 
  File: test.txt
  Size: 13        	Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d	Inode: 36541391    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-09-26 01:56:14.908738830 +0000
Modify: 2023-09-26 01:56:14.909738832 +0000
Change: 2023-09-26 01:56:24.606757763 +0000
 Birth: -
#4.主机上查看test.txt文件的inode
[root@k8s-master ~]# stat test.txt 
  File: ‘test.txt’
  Size: 13        	Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d	Inode: 36541391    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2023-09-26 09:56:14.908738830 +0800
Modify: 2023-09-26 09:56:14.909738832 +0800
Change: 2023-09-26 09:56:24.606757763 +0800
 Birth: -
#目前看来2个文件的inode都是一致的
#5.修改本机test.txt文件,保存后再次查看test.txt文件的inode
[root@k8s-master ~]# vim test.txt
[root@k8s-master ~]# cat test.txt 
hello docker
hello k8s
[root@k8s-master ~]# stat test.txt 
  File: ‘test.txt’
  Size: 23        	Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d	Inode: 33704265    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2023-09-26 10:01:44.577441268 +0800
Modify: 2023-09-26 10:01:44.577441268 +0800
Change: 2023-09-26 10:01:44.577441268 +0800
 Birth: -
此刻发现inode变化了
#6.在去容器查看test.txt文件的inode
root@7055764ca5bf:~# stat test.txt 
  File: test.txt
  Size: 13        	Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d	Inode: 36541391    Links: 0
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-09-26 02:01:36.616390058 +0000
Modify: 2023-09-26 01:56:14.909738832 +0000
Change: 2023-09-26 02:01:44.577441268 +0000
 Birth: -
#发现未变
#7.退出容器后再重新启动容器,在查看test.txt文件inode
root@7055764ca5bf:~# exit
exit
[root@k8s-master ~]# docker run -it --rm -v /root/test.txt:/root/test.txt ubuntu
root@4641ee99073c:/# cd  
root@4641ee99073c:~# stat test.txt 
  File: test.txt
  Size: 23        	Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d	Inode: 33704265    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-09-26 02:02:35.341767813 +0000
Modify: 2023-09-26 02:01:44.577441268 +0000
Change: 2023-09-26 02:01:44.577441268 +0000
 Birth: -
root@4641ee99073c:~# 
#发现容器test.txt文件inode与本机一致,说明容器重启后可以再次挂载上修改后的test.txt

1.Docker中,mount volume的原理是借用了linux namespace中的mount namespace,隔离系统中不同进程的挂载点视图,实际文件是没有变化的,在container中,bash实际上就是运行在宿主机上的进程,被Docker用linux分别隔离了mount namespace、UTS namespace、IPC namespace、PID namespace、Network namespace和User namespace,使得它看上去好像是运行在一个独立的、相对隔离的系统上,实际上它的一切资源都是宿主机在不同NameSpace中的投影,文件也不例外。

2.而Linux中,判断文件是否改变的是其inode值,如果两个文件的inode相同,两个文件必为同一文件。

3.vi和vim编辑文件的过程:

          1.复制出一个需要修改文件的副本,命名在之前的基础上加了".swap"的后缀和"."的前缀

          2.修改内容保存到有.swap后缀的文件,并flush硬盘

          3.执行:wq就会交换原文件的名称

          4.删除临时.swap文件

4.避免方法

        1.用echo 修改文件而不用vi

        2.修改vim配置,执行vim命令,输入:scriptnames查看vim的配置文件路径,在配置文件最后两行增加

set backup
set backupcopy=yes

        3.修改文件权限,文件默认权限时644,修改为666,这样修改后再通过vi修改不会修改inode

        4.挂载目录而不是文件 

2. 数据卷容器

我们启动一个数据卷容器dbdata,挂载到本地/dbdata目录

docker run -it --rm --name dbdate -v /dbdata:/dbdata ubuntu      #dbdata容器ID:227f9ea3a45a

[root@k8s-master ~]# docker run -it --remove --name dbdate -v /dbdata:/dbdata ubuntu
root@227f9ea3a45a:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay          18G  8.6G  9.2G  49% /
tmpfs            64M     0   64M   0% /dev
tmpfs           910M     0  910M   0% /sys/fs/cgroup
shm              64M     0   64M   0% /dev/shm
/dev/sda3        18G  8.6G  9.2G  49% /dbdata
tmpfs           910M     0  910M   0% /proc/asound
tmpfs           910M     0  910M   0% /proc/acpi
tmpfs           910M     0  910M   0% /proc/scsi
tmpfs           910M     0  910M   0% /sys/firmware


在创建一个db1的容器,挂载到dbdata目录

docker run -it --rm  -v /dbdata:/dbdata --name db1 ubuntu    #db1的容器ID:865bd9bf7ec9

[root@k8s-master ~]# docker run -it --rm  -v /dbdata:/dbdata --name db1 ubuntu
root@865bd9bf7ec9:/# df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay          18G  8.6G  9.2G  49% /
tmpfs            64M     0   64M   0% /dev
tmpfs           910M     0  910M   0% /sys/fs/cgroup
shm              64M     0   64M   0% /dev/shm
/dev/sda3        18G  8.6G  9.2G  49% /dbdata
tmpfs           910M     0  910M   0% /proc/asound
tmpfs           910M     0  910M   0% /proc/acpi
tmpfs           910M     0  910M   0% /proc/scsi
tmpfs           910M     0  910M   0% /sys/firmware

现在在本机/dbdata里面去创建一个tets文件

[root@k8s-master data]# cd /dbdata/
[root@k8s-master dbdata]# ls
[root@k8s-master dbdata]# touch test.txt
[root@k8s-master dbdata]# ls
test.txt
[root@k8s-master /]# chmod -R 777 dbdata/

在dbdata和db1里面查看dbdata目录下文件

root@865bd9bf7ec9:/# ls /dbdata/
test.txt
root@227f9ea3a45a:/# ls /dbdata/
test.txt

我们在去dbdata里面创建文件,db1也能看到

#1.dbdata里面创建test-$container-id.txt文件
root@227f9ea3a45a:/dbdata#touch  test-227f9ea3a45a.txt
root@227f9ea3a45a:/dbdata# ls -la
total 0
drwxrwxrwx. 2 root root 51 Sep 26 02:35 .
drwxr-xr-x. 1 root root 20 Sep 26 02:35 ..
-rw-r--r--. 1 root root  0 Sep 26 02:35 test-227f9ea3a45a.txt
-rwxrwxrwx. 1 root root  0 Sep 26 02:28 test.txt
#2.去db1容器查看
root@865bd9bf7ec9:/dbdata# ls
test-227f9ea3a45a.txt  test.txt
#3.去本机查看
[root@k8s-master dbdata]# ls -la
total 0
drwxrwxrwx.  2 root root  51 Sep 26 10:35 .
dr-xr-xr-x. 21 root root 277 Sep 26 09:26 ..
-rw-r--r--.  1 root root   0 Sep 26 10:35 test-227f9ea3a45a.txt
-rwxrwxrwx.  1 root root   0 Sep 26 10:28 test.txt

tips:1.如果本实验不成功,大概率就是/dbdata目录权限问题(chmod -R 777 /dbdata)

2.在Docker容器退出时,默认容器内部的文件系统仍然被保留,以方便调试并保留用户数据,我们可以使用docker rm -v $container-id命令指定同时删除关联容器及其挂载的数据卷

我们也可以用docker run -it --rm删除容器时会删除其挂载的数据卷,等同于容器退出后执行docker rm -v命令

3.利用数据卷容器来迁移数据

3.1 备份

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

用ubuntu启动一个名为worker的容器,--volumes-from dbdata:让worker容器挂载dbdata的容器卷,使用-v $(pwd):/backup 将本地当前目录(~/)挂载到容器的backup目录,在运行tar cvf /backup/backup.tar /dbdata

[root@k8s-master ~]# docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata
tar: Removing leading `/' from member names
/dbdata/
/dbdata/test.txt
/dbdata/test-227f9ea3a45a.txt
#宿主机ls
[root@k8s-master ~]# ls
anaconda-ks.cfg  backup.tar  Dockerfile  docker-tag.sh  dockertags.sh  harbor  original-ks.cfg  ssh_test.sh  test.tar  test.txt  ubuntu.tar  wyx.sh

3.2 恢复

创建一个名为dbdata2的容器:

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

挂载数据卷并解压恢复:

docker run --volumes-from dbdata2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar
 

[root@k8s-master ~]# docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
[root@k8s-master ~]# docker run --volumes-from dbdata2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar
dbdata/
dbdata/test.txt
dbdata/test-227f9ea3a45a.txt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值