定义

  • Docker 理念回顾:
    • 将应用和环境打包成一个镜像
  • 将数据保存在容器中的后果:
    • 如果将容器删除, 数据就会丢失
    • 需要将数据持久化, 例如将MySQL 的数据存储在本地
    • 解决方案:
      • 容器之间有一个数据共享的技术, Docker 容器中产生的数据, 同步到本地
      • 以上的实现技术叫做卷技术, 本质上就是目录的挂载, 将容器内的目录挂载到Linux 文件系统中, 如下图所示:

image.png

  1. - 总结: **容器的持久化和同步操作, 且容器间的数据共享.**


作用:

  • 修改配置, 数据等的数据只需在本地修改即可, 无需进入容器, docker 会自动同步


使用数据卷

方式1: 使用命令来挂载 -v

  1. #命令说明
  2. docker run -it -v 主机目录: 容器内目录
  • 例子:

    1. docker run -it -v /home/test:/home centos /bin/bash

    image.png

    • 进入容器的home 目录创建test.java 文件, 可以发现自动同步到了Linux 宿主机上的/home/test 目录下

      • 首先要确保selinux未禁用:
        1. setenforce 0
        2. getenforce
        3. Permissive
        1. [root@5428417d8963 /]# cd /home
        2. [root@5428417d8963 home]# touch test.java
        image.png
    • 注: 即使容器关闭, 在宿主机上改变文件内容, 再下次启动容器后, docker 也会同步修改到容器中

方式2: 通过Dockerfile 生成镜像启动自动挂载

  • 详见初始Dockerfile 测试步骤

    MySQL 容器的数据持久化问题

    ```shell

    获取镜像

    docker pull mysql:5.7

运行容器, 需要做数据挂载

安装启动mysql, 需要配置密码的!

官方命令

docker run —name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

命令实例:

-d: 后端运行 -p: 端口映射 -v: 数据卷挂载 -e: 环境配置 —name: 容器名字 docker run -d -p 3310:3306 -v /home/mysql/conf:/ect/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 —name mysql01 mysql:5.7

启动成功之后, 可以使用客户端工具连接MySQL

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/2516625/1643616722771-f69b9bc5-4d80-4c10-acaf-135676b3af26.png#clientId=u453074f8-f3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=469&id=uc4c6b610&margin=%5Bobject%20Object%5D&name=image.png&originHeight=821&originWidth=1445&originalType=binary&ratio=1&rotation=0&showTitle=false&size=488254&status=done&style=none&taskId=u99193dea-2370-4760-a580-0ba722cfcf1&title=&width=825.7142857142857)
  2. - 这时再创建手动创建一个数据库, 可以发现宿主机上的映射目录中出现了test 文件夹
  3. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/2516625/1643616890447-67ffcc62-2612-4c47-9542-cec541e77d34.png#clientId=u453074f8-f3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=214&id=ubea3962d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=374&originWidth=468&originalType=binary&ratio=1&rotation=0&showTitle=false&size=48789&status=done&style=none&taskId=u0df6865d-9b13-405f-9018-8caa89a7097&title=&width=267.42857142857144)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/2516625/1643616964999-3800ca39-a7f7-4bda-add3-7f1e8d89262a.png#clientId=u453074f8-f3fe-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=448&id=u899217df&margin=%5Bobject%20Object%5D&name=image.png&originHeight=784&originWidth=1425&originalType=binary&ratio=1&rotation=0&showTitle=false&size=155052&status=done&style=none&taskId=ue58dc60e-b409-4232-9045-060564c1658&title=&width=814.2857142857143)
  4. - 注: **即使删除MySQL 容器, 宿主机上的数据也不会随容器的删除而删除, 实现了数据的持久化**
  5. <a name="kF2oO"></a>
  6. # 名称
  7. - 具名挂载:
  8. - 通过-v 卷名:容器内路径来指定卷名, 例子如下
  9. ```shell
  10. #通过-v 卷名:容器内路径来指定卷名
  11. docker run -d -P --name nginx02 -v juming-nginx:/ect/nginx nginx
  12. 9d9a9d184971432ff31e6e767c0631013515e4c0da2cc373013097480ef4952a
  13. #查看数据卷列表
  14. docker volume ls
  15. DRIVER VOLUME NAME
  16. local 7f5e2029289f9601887597fb8f8c5d4b81cb9e8f89e746e4cd50d5d74c692bbe
  17. local b118ffbba045826181f85030c3741a0afaf539d82b736a7d64d2dffa8e16f721
  18. local bf2950ea03c1f06f0e8eb29bca1ee856ac27212564c2cb6e48b8ce5bc95d3835
  19. local juming-nginx
  • 匿名挂载:
    • -v 容器内路径, 例子如下: ```shell

      启动nginx

      -P: 随机映射端口

      docker run -d -P —name nginx01 -v /ect/nginx nginx

查看所有volume 情况

以下都是匿名卷挂载, 因为在-v 时只写了容器内的路径, 没有写容器外的路径

docker volume ls DRIVER VOLUME NAME local 7f5e2029289f9601887597fb8f8c5d4b81cb9e8f89e746e4cd50d5d74c692bbe local b118ffbba045826181f85030c3741a0afaf539d82b736a7d64d2dffa8e16f721 local bf2950ea03c1f06f0e8eb29bca1ee856ac27212564c2cb6e48b8ce5bc95d3835

  1. - 指定路径挂载
  2. - -v /宿主机路径:容器内路径
  3. <a name="LKDuF"></a>
  4. # 查看数据卷的映射目录
  5. - 命令:
  6. ```shell
  7. #命令模板
  8. docker volume inspect 卷名
  9. #命令实例
  10. docker volume inspect juming-nginx
  1. #查看上例中nginx 挂载的数据卷的映射目录
  2. docker volume inspect juming-nginx
  3. [
  4. {
  5. "Driver": "local",
  6. "Labels": null,
  7. "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
  8. "Name": "juming-nginx",
  9. "Options": {},
  10. "Scope": "local"
  11. }
  12. ]
  • 注: 所有的docker 容器内的卷, 没有指定目录的情况下都是在 /var/lib/docker/volumes/xxx/_data 目录

image.png

  • 通过具名挂载, 可以方便的找到具体的数据卷, 大多数情况下使用具名挂载
  • 拓展: ```shell

    通过 -v 容器内路径: ro/rw 来改变读写权限

    ro readonly 只读

    rw readwrite 可读可写

一旦设置了容器权限, 容器对我们挂载出来的内容就有限定了

docker run -d -P —name nginx02 -v juming-nginx:/ect/nginx:ro nginx docker run -d -P —name nginx02 -v juming-nginx:/ect/nginx:rw nginx

ro: 只能从宿主机改变, 不能从容器内部改变

rw: 都能改变

  1. <a name="DsGyj"></a>
  2. # 初识Dockerfile
  3. - 定义:
  4. - 用来构建Docker 镜像的构建文件
  5. - 本质:
  6. - 命令脚本, 通过这本脚本可以生成镜像, 镜像是一层一层的, 脚本是一个个的命令, 每个命令就是一层
  7. - 测试:
  8. ```shell
  9. #创建dockerfile 文件, 名字可以随机, 建议使用dockerfile 即可
  10. #以下是文件中的内容, 指令(大写) 参数
  11. FROM centos
  12. #这里将volume01 和volume02 两个目录挂载到容器
  13. VOLUME ["volume01", "volume02"]
  14. CMD echo "----end----"
  15. CMD /bin/bash
  16. #这里的每个命令, 可以理解为镜像的一层
  1. # 通过build 命令生成镜像
  2. #-f: 后面跟dockerfile 路径
  3. #-t: 后面跟镜像名:版本
  4. #最后的.: 表示生成在当前目录下
  5. docker build -f ./dockerfile1 -t flm/centos:1.0 .
  6. #查看本地镜像
  7. docker images
  8. #发现有flm/centos 根据dockerfile 生成的镜像
  9. REPOSITORY TAG IMAGE ID CREATED SIZE
  10. flm/centos 1.0 2a2883c6abed 27 seconds ago 231 MB
  11. tomcat-2 1.0 6fd68ca2420f 7 hours ago 684 MB
  12. docker.io/tomcat 9.0 df8f7f1177ca 3 days ago 680 MB
  13. docker.io/tomcat latest 413407dddb5e 3 days ago 680 MB
  14. docker.io/mysql 5.7 0712d5dc1b14 4 days ago 448 MB
  15. docker.io/mysql 8.0 d1dc36cf8d9e 4 days ago 519 MB
  16. docker.io/mysql latest d1dc36cf8d9e 4 days ago 519 MB
  17. docker.io/redis latest f1b6973564e9 4 days ago 113 MB
  18. docker.io/nginx latest c316d5a335a5 5 days ago 142 MB
  19. docker.io/hello-world latest feb5d9fea6a5 4 months ago 13.3 kB
  20. docker.io/centos latest 5d0da3dc9764 4 months ago 231 MB
  21. docker.io/portainer/portainer latest 580c0e4e98b0 10 months ago 79.1 MB
  22. docker.io/elasticsearch 7.6.2 f29a1ee41030 22 months ago 791 MB
  23. #启动镜像
  24. docker run -it 2a2883c6abed
  25. #可以看到容器中存在两个目录volume01 和volume02, 且这两个目录就是在生成镜像的时候自动挂载的数据卷的目录
  26. #因为挂载了数据卷, 说明外部一定有对应的目录
  27. ls -l
  28. total 0
  29. lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
  30. drwxr-xr-x. 5 root root 360 Jan 31 14:03 dev
  31. drwxr-xr-x. 1 root root 66 Jan 31 14:03 etc
  32. drwxr-xr-x. 2 root root 6 Nov 3 2020 home
  33. lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib
  34. lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
  35. drwx------. 2 root root 6 Sep 15 14:17 lost+found
  36. drwxr-xr-x. 2 root root 6 Nov 3 2020 media
  37. drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
  38. drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
  39. dr-xr-xr-x. 236 root root 0 Jan 31 14:03 proc
  40. dr-xr-x---. 2 root root 162 Sep 15 14:17 root
  41. drwxr-xr-x. 1 root root 21 Jan 31 14:03 run
  42. lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
  43. drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
  44. dr-xr-xr-x. 13 root root 0 Jan 31 06:44 sys
  45. drwxrwxrwt. 7 root root 171 Sep 15 14:17 tmp
  46. drwxr-xr-x. 12 root root 144 Sep 15 14:17 usr
  47. drwxr-xr-x. 20 root root 262 Sep 15 14:17 var
  48. drwxr-xr-x. 2 root root 6 Jan 31 14:03 volume01
  49. drwxr-xr-x. 2 root root 6 Jan 31 14:03 volume02
  50. #通过inspect 或者volume ls + volume inspect 卷ID 命令来查看数据卷的映射目录
  51. #这边选择第一种
  52. ...
  53. "Mounts": [
  54. {
  55. "Type": "volume",
  56. "Name": "3fdc6a39f02de016a8beda5ede1bf64be701d20c9f29dc124750c8e738ae472d",
  57. "Source": "/var/lib/docker/volumes/3fdc6a39f02de016a8beda5ede1bf64be701d20c9f29dc124750c8e738ae472d/_data",
  58. "Destination": "volume02",
  59. "Driver": "local",
  60. "Mode": "",
  61. "RW": true,
  62. "Propagation": ""
  63. },
  64. {
  65. "Type": "volume",
  66. "Name": "ffa8017d3624850d8a355778266f0363e4a056aebfcebe365f71d071e5c9f254",
  67. "Source": "/var/lib/docker/volumes/ffa8017d3624850d8a355778266f0363e4a056aebfcebe365f71d071e5c9f254/_data",
  68. "Destination": "volume01",
  69. "Driver": "local",
  70. "Mode": "",
  71. "RW": true,
  72. "Propagation": ""
  73. }
  74. ]
  75. ...
  76. #进入容器的volume01 目录, 创建文件, 观察宿主机中的映射目录, 可以发现刚才在容器中创建的文件自动同步到了宿主机上
  77. [root@bf805ada549c volume01]# touch container.txt
  78. [root@localhost _data]# ls -l
  79. total 0
  80. -rw-r--r--. 1 root root 0 Jan 31 09:15 container.txt
  • 注: 如果在构建镜像的时候没有挂载卷, 则需要手动挂载, 使用-v 卷名:容器内路径

数据卷容器

  • 定义:
    • 实现两个或者多个容器之间的数据共享

image.png

  • 使用命令:

    1. run 命令中的参数: --volumes-from 容器名
  • 测试: ```shell

    启动3 个容器, 通过自定义镜像启动

    启动第1 个容器, 容器名为docker01

    docker run -it —name docker01 2a2883c6abed

在容器中发现有volume01 目录

[root@00e5f74ef4c3 /]# ls -l total 0 lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x. 5 root root 360 Jan 31 14:32 dev drwxr-xr-x. 1 root root 66 Jan 31 14:32 etc drwxr-xr-x. 2 root root 6 Nov 3 2020 home lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64 drwx———. 2 root root 6 Sep 15 14:17 lost+found drwxr-xr-x. 2 root root 6 Nov 3 2020 media drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt drwxr-xr-x. 2 root root 6 Nov 3 2020 opt dr-xr-xr-x. 238 root root 0 Jan 31 14:32 proc dr-xr-x—-. 2 root root 162 Sep 15 14:17 root drwxr-xr-x. 1 root root 21 Jan 31 14:32 run lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin drwxr-xr-x. 2 root root 6 Nov 3 2020 srv dr-xr-xr-x. 13 root root 0 Jan 31 06:44 sys drwxrwxrwt. 7 root root 171 Sep 15 14:17 tmp drwxr-xr-x. 12 root root 144 Sep 15 14:17 usr drwxr-xr-x. 20 root root 262 Sep 15 14:17 var drwxr-xr-x. 2 root root 6 Jan 31 14:30 volume01 drwxr-xr-x. 2 root root 6 Jan 31 14:30 volume02 [root@00e5f74ef4c3 /]# cd ./volume01

启动第二个容器, 容器名为docker02, 且与docker01 进行数据共享

—volumes-from: 后面跟需要同步数据的容器名

docker run -it —name docker02 —volumes-from docker01 2a2883c6abed

在docker02 创建文件

[root@localhost home]# docker attach ac106f5bbb4b [root@ac106f5bbb4b /]# cd /volume01 [root@ac106f5bbb4b volume01]# touch docker01

在docker01 查看同步过来的文件

[root@00e5f74ef4c3 volume01]# ls -l total 0 -rw-r—r—. 1 root root 0 Jan 31 14:33 docker01

  1. - 注:
  2. - **docker01 叫做数据卷容器 (被同步的容器), 即使再创建容器将docker01 挂载上, 一样可以实现数据同步**
  3. - **即使删除docker01, 其他容器中的数据依然存在**
  4. - **数据卷容器的数据同步是一个双向拷贝的概念, 可以理解为各个容器的数据进行互相备份 (拷贝的过程), 即使删除其中一个, 也不会因为这一个容器被删除了, 其他容器的数据也不会丢失**
  5. - **容器之间配置信息的传递, 数据卷容器的生命周期一直持续到没有容器使用为止, 但是一旦持久化到了本地, 这个时候, 本地的数据是不会删除的**
  6. <a name="IrXZ3"></a>
  7. # 多个MySQL 实现数据共享
  8. ```shell
  9. #启动第一个MySQL
  10. docker run -d -p 3310:3306 -v /home/mysql/conf:/ect/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
  11. #启动第二个MySQL 进行数据卷挂载
  12. docker run -d -p 3310:3306 -v /home/mysql/conf:/ect/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7