docker 数据管理

Docker 内部管理数据主要有两种方式:

  • 数据卷:Data Volumes 容器内数据直接映射到本地主机环境
  • 数据卷容器:Data Volume Containers 使用特定容器维护数据卷

数据卷

当我们在使用docker容器的时候,会产生一系列的数据文件,这些数据文件在我们删除docker容器时是
会消失的,但是其中产生的部分内容我们是希望能够把它给保存起来另作用途的,Docker将应用与运行环境打包成容器发布,我们希望在运行过程钟产生的部分数据是可以持久化的的,而且容器之间我们希望能够实现数据共享。
通俗地来说,docker容器数据卷可以看成使我们生活中常用的u盘,它存在于一个或多个的容器中,由docker挂载到容器,但不属于联合文件系统,Docker不会在容器删除时删除其挂载的数据卷。

  • 数据卷可以在容器之间共享和重用
  • 对数据卷的修改会立马生效
  • 对数据卷的更新,不会影响镜像
  • 数据卷默认会一直存在,即使容器被删除

数据卷挂载支持三种方式,tmpfs、volume、mount

tmpfs 非数据持久化方式。将数据卷挂载到宿主机内存中。建议只用于测试使用。
mount 将宿主机的目录挂载到容器里,操作权限在宿主机。
volume 将宿主机的目录与容器目录做绑定映射,操作权限在容器。
Docker数据卷 - 图1


因docker官方强烈推荐使用volume,所以下面只叙述volume的用法

注意:数据卷的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷。

mount示例:

使用 -v 标记也可以指定挂载一个本地主机的目录到容器中去,不存在的目录会自动创建。

  1. docker run ... -v 宿主机目录(文件):容器内目录(文件) ... # 宿主名目录(文件)的路径为绝对路径

宿主机内本来没有的文件,在容器内部创建后宿主机可以搜索到,重启容器或者宿主机是不会消失。
一旦删除容器,容器层数据将会删除,宿主机内数据也会删除。

  1. [root@vms10 ~]# find / -name aaaa
  2. [root@vms10 ~]# docker ps
  3. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  4. 567dd209b8c6 nginx "/docker-entrypoint.…" 58 seconds ago Up 57 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp web
  5. [root@vms10 ~]# docker exec -it web bash
  6. root@567dd209b8c6:/# touch aaaa
  7. root@567dd209b8c6:/# exit
  8. exit
  9. [root@vms10 ~]# find / -name aaaa
  10. /var/lib/docker/overlay2/0a1738208d13307fba4a11a26f389b8cb4817b27edb89b06b9a992c52c99f430/diff/aaaa
  11. /var/lib/docker/overlay2/0a1738208d13307fba4a11a26f389b8cb4817b27edb89b06b9a992c52c99f430/merged/aaaa
  12. [root@vms10 ~]# docker restart web
  13. web
  14. [root@vms10 ~]# find / -name aaaa
  15. /var/lib/docker/overlay2/0a1738208d13307fba4a11a26f389b8cb4817b27edb89b06b9a992c52c99f430/diff/aaaa
  16. /var/lib/docker/overlay2/0a1738208d13307fba4a11a26f389b8cb4817b27edb89b06b9a992c52c99f430/merged/aaaa
  17. [root@vms10 ~]# docker rm -f web
  18. web
  19. [root@vms10 ~]# find / -name aaaa
  20. [root@vms10 ~]#

image.png

-v 指定挂载一个宿主机的目录到容器中去,容器内部写数据会映射到宿主机中,删除容器后宿主机数据还在。

1、如果只指定一个目录那么这个目录是容器内的目录,此目录不存在会自动生成,并且不指定宿主机中路径会自动映射挂载到其中宿主机的一个目录。

  1. [root@vms10 ~]# docker run -itd --name=web --restart=always -v /data nginx
  2. # 查看宿主机中挂在路径
  3. [root@vms10 ~]# docker inspect web
  4. "Mounts": [
  5. {
  6. "Type": "volume",
  7. "Name": "51bdef00681072466505d3f96dfe3acc70f4b13025c96003e5f079418f6942d3",
  8. "Source ": "/var/lib/docker/volumes/51bdef00681072466505d3f96dfe3acc70f4b13025c96003e5f079418f6942d3/_data",
  9. "Destination": "/data",
  10. "Driver": "local",
  11. "Mode": "",
  12. "RW": true,
  13. "Propagation": ""
  14. }
  15. # Destination 容器内的目录
  16. # Source 宿主机内的目录

此时间从容器内创建数据在宿主机可以看到,在宿主机创建数据后在容器内也可以看到。

  1. [root@vms10 ~]# ls /var/lib/docker/volumes/51bdef00681072466505d3f96dfe3acc70f4b13025c96003e5f079418f6942d3/_data
  2. [root@vms10 ~]# docker exec -it web bash
  3. root@74a770517427:/# ls /data/
  4. root@74a770517427:/# touch /data/aaaa
  5. root@74a770517427:/# ls /data/
  6. aaaa
  7. root@74a770517427:/# exit
  8. exit
  9. [root@vms10 ~]# ls /var/lib/docker/volumes/51bdef00681072466505d3f96dfe3acc70f4b13025c96003e5f079418f6942d3/_data
  10. aaaa
  11. [root@vms10 ~]# touch /var/lib/docker/volumes/51bdef00681072466505d3f96dfe3acc70f4b13025c96003e5f079418f6942d3/_data/bbbb
  12. [root@vms10 ~]# docker exec -it web bash
  13. root@74a770517427:/# ls /data/
  14. aaaa bbbb

image.png
删除容器后,宿主机数据还存在

  1. [root@vms10 ~]# docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  3. 74a770517427 nginx "/docker-entrypoint.…" 7 minutes ago Up 7 minutes 80/tcp web
  4. [root@vms10 ~]# docker rm -f web
  5. web
  6. [root@vms10 ~]# ls /var/lib/docker/volumes/51bdef00681072466505d3f96dfe3acc70f4b13025c96003e5f079418f6942d3/_data
  7. aaaa bbbb
  8. [root@vms10 ~]#

image.png再次指定容器内/data 重新创建容器,内部/data数据将不存在,因为宿主机对应的路径变化了,所以不要光指定一个目录路径
image.png

2、指定宿主机与容器内两个路径,不存在的目录会自动创建

  1. [root@vms10 ~]# ls /xx
  2. ls: 无法访问/xx: 没有那个文件或目录
  3. [root@vms10 ~]# docker run -itd --name=web --restart=always -v /xx:/data nginx
  4. cbccbb5e12fcd4120033f0b3f409f6666aff3daa580f49388b6d8d7212c1cc59
  5. [root@vms10 ~]# ls /xx
  6. [root@vms10 ~]# docker inspect web
  7. "Mounts": [
  8. {
  9. "Type": "bind",
  10. "Source": "/xx",
  11. "Destination": "/data",
  12. "Mode": "",
  13. "RW": true,
  14. "Propagation": "rprivate"
  15. }

image.png

创建文件测试都是存在的

  1. [root@vms10 ~]# ls /xx
  2. [root@vms10 ~]# docker exec -it web bash
  3. root@cbccbb5e12fc:/# ls /data/
  4. root@cbccbb5e12fc:/# touch /data/aaaa
  5. root@cbccbb5e12fc:/# ls /data/
  6. aaaa
  7. root@cbccbb5e12fc:/# exit
  8. exit
  9. [root@vms10 ~]# ls /xx
  10. aaaa
  11. [root@vms10 ~]# touch /xx/bbbb
  12. [root@vms10 ~]# docker exec -it web bash
  13. root@cbccbb5e12fc:/# ls /data/
  14. aaaa bbbb
  15. root@cbccbb5e12fc:/#

image.png

删除容器后,在重新创建指定之前目录进入后数据还是存在的。

  1. [root@vms10 ~]# docker rm -f web
  2. web
  3. [root@vms10 ~]# docker run -itd --name=web --restart=always -v /xx:/data nginx
  4. ffb0678eb1902fbb63c619aebe78ad2294132bd52f88620e8e18cdee9f3502b0
  5. [root@vms10 ~]# docker exec -it web bash
  6. root@ffb0678eb190:/# ls /data/
  7. aaaa bbbb
  8. root@ffb0678eb190:/#

image.png

默认执行的命令后是隐藏了权限的设置,正常的话是
[root@vms10 ~]# docker run -itd —name=web —restart=always -v /xx:/data:rw nginx
不写的话默认就是rw读写权限。也可以设置只读权限
[root@vms10 ~]# docker run -itd —name=web —restart=always -v /xx:/data:ro nginx
那么启动容器后进入到容器内部则是只读操作/data目录

volume 示例

通过创建docker volumes ,docker会把数据存放在默认配置的路径。

  1. [root@vms10 ~]# docker volume list # 查看volume列表
  2. DRIVER VOLUME NAME
  3. local 631f3a65bc09729fa0a98ff47d4daa54f9dd9ed02c77365e004ee75cb6626138
  4. local 742e3f8289754c663670740f67feeb5abfcaff61dc22f023d2beda3b7677d6b6
  5. [root@vms10 ~]# docker volume create v1 # 创建volume
  6. v1
  7. [root@vms10 ~]# docker volume list
  8. DRIVER VOLUME NAME
  9. local 631f3a65bc09729fa0a98ff47d4daa54f9dd9ed02c77365e004ee75cb6626138
  10. local 742e3f8289754c663670740f67feeb5abfcaff61dc22f023d2beda3b7677d6b6
  11. local v1
  12. [root@vms10 ~]# docker volume inspect v1 # 查看volume详细信息
  13. [
  14. {
  15. "CreatedAt": "2022-03-03T03:38:30+08:00",
  16. "Driver": "local",
  17. "Labels": {},
  18. "Mountpoint": "/var/lib/docker/volumes/v1/_data",
  19. "Name": "v1",
  20. "Options": {},
  21. "Scope": "local"
  22. }
  23. ]
  24. # Mountpoint 宿主机目录

可以直接指定上述volume进行启动容器

  1. [root@vms10 ~]# docker volume inspect v1
  2. [
  3. {
  4. "CreatedAt": "2022-03-03T03:38:30+08:00",
  5. "Driver": "local",
  6. "Labels": {},
  7. "Mountpoint": "/var/lib/docker/volumes/v1/_data",
  8. "Name": "v1",
  9. "Options": {},
  10. "Scope": "local"
  11. }
  12. ]
  13. [root@vms10 ~]# ls /var/lib/docker/volumes/v1/_data
  14. [root@vms10 ~]# docker run -itd --name=web --restart=always -v v1:/data nginx
  15. 41b3b7d6ba4859232df1695522575bd685c8ec899280e9cf56b9c1382007ceed
  16. [root@vms10 ~]# docker exec -it web bash
  17. root@41b3b7d6ba48:/# ls /data/
  18. root@41b3b7d6ba48:/# touch /data/aaaa
  19. root@41b3b7d6ba48:/# ls /data/
  20. aaaa
  21. root@41b3b7d6ba48:/# exit
  22. exit
  23. [root@vms10 ~]# ls /var/lib/docker/volumes/v1/_data
  24. aaaa
  25. [root@vms10 ~]# touch /var/lib/docker/volumes/v1/_data/bbbb
  26. [root@vms10 ~]# docker exec -it web bash
  27. root@41b3b7d6ba48:/# ls /data/
  28. aaaa bbbb
  29. root@41b3b7d6ba48:/#

image.png

如果忘记了容器内部挂载的目录是/data ,那么做这个数据卷意义何在?