zoukankan      html  css  js  c++  java
  • Docker——容器数据卷

    1. 为什么需要容器数据卷

      角度:遇到问题,尝试以朴素的道理解决问题.问题复杂化,解决的方式也变得复杂

      问题的提出:docker将应用和环境打包成一个镜像,但是对于容器内的数据,如果不进行外部的保存,那么当容器删除后,数据也会丢失

      解决:通过docker的容器数据卷技术,实现容器数据的持久化和同步操作!同时容器间也是可以数据共享的!

      实现:目录的挂载,将我们容器内的目录,挂载到Linux上面,使两者之间相互对应

    2. 使用数据卷

      建议使用两个终端进行调试

      • docker run -v 主机目录地址:容器目录地址:将主机目录地址与对应的容器目录地址进行双向绑定

        v:类似vue的v-model双向绑定(注:v-bind和v-model的区别在于v-bind多用于单向绑定,比如字段的显示;v-model则多用于表单,比如input中输入的返回等)

        测试:

        #运行一个容器,同时制定行管的目录
        [root@iZwz908j8pbqd86doyrez5Z test]# docker run -d -it -v /test:/root/test -p 8081:8080 tomcat:9.0 /bin/bash
        a5c3db57e2b230db84a9d273e2379d55b47b47bc07f5630d16a35d1e5fc0c3b0
        [root@iZwz908j8pbqd86doyrez5Z test]# docker ps
        CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
        a5c3db57e2b2        tomcat:9.0          "/bin/bash"         14 seconds ago      Up 14 seconds       0.0.0.0:8081->8080/tcp   sad_tu
        [root@iZwz908j8pbqd86doyrez5Z test]# docker attach a5c3db57e2b2
        
        #从元数据中查看绑定情况
        "Mounts": [
        {
        "Type": "bind",
        "Source": "/root/test",  //源文件位置(主机)
        "Destination": "/root/test",  //目标文件位置(容器)
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
        }
        ]
        
        #尝试从容器写入主机
        #容器
        [root@6eec281a5e9f test]# mkdir test1
        [root@6eec281a5e9f test]# ls
        test.java  test1
        #主机
        [root@iZwz908j8pbqd86doyrez5Z test]# ls
        test1  test.java
        
        #尝试从主机写入容器
        #主机
        [root@iZwz908j8pbqd86doyrez5Z test]# touch a.tets
        [root@iZwz908j8pbqd86doyrez5Z test]# ls
        a.tets  test1  test.java
        #容器
        [root@6eec281a5e9f test]# ls
        a.tets	test.java  test1
        

        注:

        • -it:以交互的形式打开终端,-d:在后台运行
        • 只有在运行时用-it...bash,才能在之后用attach打开一个命令行
        • 主次关系来说,其实还是主机的目录覆盖容器的目录

        优点:修改只需在本地修改即可,容器内会自动同步

    3. 安装mysql完成挂载

      mysql所有数据都在data目录下

      #下载镜像
      docker pull mysql:5.7
      
      #在使用挂载对mysql的相关目录覆盖之前,我们需要保证目录中有所需要的东西
      #新建一下目录:/usr/arno/mysql/conf,/usr/arno/mysql/data
      #打开一个不需要挂载的mysql容器,将容器内对应的数据复制到新建的目录中
      [root@iZwz908j8pbqd86doyrez5Z conf]# docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 mysql:5.7
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker cp ad7db127211a:/etc/mysql/conf.d /usr/arno/mysql/conf
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker cp ad7db127211a:/var/lib/mysql /usr/arno/mysql/data
      
      #运行镜像(同时对mysql的conf和data进行了挂载)
      docker run -d -p 3310:3306 -v /usr/arno/mysql/conf:/etc/mysql/conf.d -v /usr/arno/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
      
      #尝试通过navicat访问(需要配置阿里云安全组)
      #(1).连接成功(欧耶!)
      #(2).新建一个数据库(test)
      
      #查看主机中的data
      [root@iZwz908j8pbqd86doyrez5Z data]# ls
      auto.cnf    client-cert.pem  ibdata1      ibtmp1              private_key.pem  server-key.pem
      ca-key.pem  client-key.pem   ib_logfile0  mysql               public_key.pem   sys
      ca.pem      ib_buffer_pool   ib_logfile1  performance_schema  server-cert.pem  test
      
      #查看容器中的数据库
      root@78c6defe3428:/var/lib/mysql# ls
      auto.cnf    client-cert.pem  ib_logfile0  ibtmp1	      private_key.pem  server-key.pem
      ca-key.pem  client-key.pem   ib_logfile1  mysql		      public_key.pem   sys
      ca.pem	    ib_buffer_pool   ibdata1	  performance_schema  server-cert.pem  test
      
      #完美!
      

      注:

      • 通过hub.docker搜查mysql,以便完成mysql密码的配置$ docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
      • 注意:挂载的开始,主机的目录会覆盖容器的目录,所以你的目录必须一开始就要有对应的文件.解决方法就是运行一个不挂载的容器,然后将所有东西都用docker cp 容器id:目录 要主机目录命令拷贝到主机目录下(但更好的方法是使用下面的具名挂载)
    4. 具名挂载与匿名挂载

      #1.匿名挂载
      -v 容器内路径
      docker run -d -P --name nginx01 -v /etc/nginx nginx
      
      #查看所有挂载的卷
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker volume ls  
      DRIVER              VOLUME NAME
      local               2e364979e68adc93ea6ac8075250d0f41488c62b0345db8a917f8571df312992
      local               811aa7cb9f25b11fffb8a6e3490726f6d85b28f73147a7bceb8096288aa70163
      local               c1abdabde73dcf238913e7f51aa4bcd726f170a474d3282f704f19bc86f40be0
      local               f0e7e07b67bf298bdf8c3d420f93c5851c0cfa313669cfd1887f4a3210e73c62
      #匿名卷挂载形式(在-v时只写了容器内的路径,没有写容器外的路径)
      
      #通过原数据查看匿名挂载的卷
      "Mounts": [
      {
      "Type": "volume",
      "Name": "811aa7cb9f25b11fffb8a6e3490726f6d85b28f73147a7bceb8096288aa70163",  #对应的匿名
      "Source": "/var/lib/docker/volumes/811aa7cb9f25b11fffb8a6e3490726f6d85b28f73147a7bceb8096288aa70163/_data",
      #匿名挂载对应的主机路径
      "Destination": "-etc/nginx",  #匿名挂载对应的容器路径
      "Driver": "local",
      "Mode": "",
      "RW": true,
      "Propagation": ""
      }
      
      #2.具名挂载
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker run -d -P --name nginx02 -v volume:/etc/nginx nginx
      d4a2fed1744e7c8ed2e3febe35612842a01eb8379d159b437de752e0b6c25ca1
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker volume ls
      DRIVER              VOLUME NAME
      local               2e364979e68adc93ea6ac8075250d0f41488c62b0345db8a917f8571df312992
      local               811aa7cb9f25b11fffb8a6e3490726f6d85b28f73147a7bceb8096288aa70163
      local               c1abdabde73dcf238913e7f51aa4bcd726f170a474d3282f704f19bc86f40be0
      local               f0e7e07b67bf298bdf8c3d420f93c5851c0cfa313669cfd1887f4a3210e73c62
      local               volume
      
      #查看具名挂载的目录
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker inspect volume
      [
          {
              "CreatedAt": "2020-09-12T09:03:07+08:00",
              "Driver": "local",
              "Labels": null,
              "Mountpoint": "/var/lib/docker/volumes/volume/_data",
              "Name": "volume",
              "Options": null,
              "Scope": "local"
          }
      ]
      
      #查看元数据中的挂载
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker inspect nginx02
      "Mounts": [
      {
      "Type": "volume",
      "Name": "volume",
      "Source": "/var/lib/docker/volumes/volume/_data",  #主机目录
      "Destination": "/etc/nginx",  #容器目录
      "Driver": "local",
      "Mode": "z",
      "RW": true,
      "Propagation": ""
      }
      ]
      

      注:

      • -P(大p):随机映射端口

      • 所有的docker容器内的卷,没有指定目录的情况下都是docker 在/var/lib/docker/volume/xxxx/_data

      • 挂载形式 指定挂载路径 有名字
        匿名挂载 false false
        指定路径挂载 true false
        具名挂载 true true

      如何区分具名挂载,匿名挂载,还是具名指定路径挂载?

      -v 容器内路径 #匿名挂载

      -v 卷名:容器内路径 #具名挂载

      -v /宿主机路径:/容器内路径 #指定路径挂载

      拓展:

      # 通过-v容器内路径,ro/rw改变读写权限
      docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx  #只读
      docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx  #只写
      

      注:只读的挂载卷只能通过宿主机来操作

    5. 初始Dockerfile

      Dockerfile就是用来构建docker镜像的构建文件和命令脚本.由于镜像是分层的,每个命令也对应一层

      #创建一个名为docker file1的文件,同时进入编辑
      vim dockerfile1
      
      #写命令(指令大写)
      FROM centos  #以centos为基础
      VOLUME ["volumen01","volume02"]  #在生成时挂载卷,匿名挂载,volume01/volume02是内部的文件
      CMD echo "----end----"
      CMD  /bin/bash  #以指令台的形式打开
      #保存退出:esc -> :wq
      
      #查看编写的文件脚本
      car dockerfile1
      
      #生成dockerfile
      [root@iZwz908j8pbqd86doyrez5Z test]# docker build -f dockerfile1 -t arno/centos:1.0 .
      Sending build context to Docker daemon  3.584kB
      Step 1/4 : FROM centos
       ---> 0d120b6ccaa8
      Step 2/4 : VOLUME ["volumen01","volume02"]
       ---> Running in e9fd99177a57
      Removing intermediate container e9fd99177a57
       ---> 4b51c5ece9de
      Step 3/4 : CMD echo "---end---"
       ---> Running in 17fc5ba5da77
      Removing intermediate container 17fc5ba5da77
       ---> ba8b29cc064e
      Step 4/4 : CMD /bin/bash
       ---> Running in 047d5ced7a4b
      Removing intermediate container 047d5ced7a4b
       ---> bbbedbad86c6
      Successfully built bbbedbad86c6
      Successfully tagged arno/centos:1.0
      #-f 生成的文件
      #-t 生成的文件名:tag 生成的文件位置(当时当前目录)
      
      #运行容器
      [root@iZwz908j8pbqd86doyrez5Z test]# docker run -it arno/centos:1.0 /bin/bash
      [root@652cd9f64f74 /]# ls
      bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volumen01
      dev  home  lib64  media       opt  root  sbin  sys  usr  volume02#可以看到有volume01和volume02两个文件
      
      #查看挂载的数据卷
      [root@iZwz908j8pbqd86doyrez5Z ~]# docker inspect 652cd9f64f74
      "Mounts": [
      {
      "Type": "volume",
      "Name": "7fe986067800aa48085b302336faa270d7df53ba65d4eb3e0964eaee6f50796a",  #匿名
      "Source": "/var/lib/docker/volumes/7fe986067800aa48085b302336faa270d7df53ba65d4eb3e0964eaee6f50796a/_data",
      "Destination": "volume02",
      "Driver": "local",
      "Mode": "",
      "RW": true,
      "Propagation": ""
      },
      {
      "Type": "volume",
      "Name": "a5e71c3f49495c1b02fa559b92fb65ecc6dee0a1ce7fd3d2fa77b2dc1341e739",  #匿名
      "Source": "/var/lib/docker/volumes/a5e71c3f49495c1b02fa559b92fb65ecc6dee0a1ce7fd3d2fa77b2dc1341e739/_data",
      "Destination": "volumen01",
      "Driver": "local",
      "Mode": "",
      "RW": true,
      "Propagation": ""
      }
      ],
      
      #测试
      #在容器中生成一个/volumen01/test.txt文件
      [root@652cd9f64f74 /]# cd volumen01
      [root@652cd9f64f74 volumen01]# touch test.txt
      [root@652cd9f64f74 volumen01]# ls
      test.txt
      #在主机中查看(直接复制元数据中mounts的source路径即可)
      [root@iZwz908j8pbqd86doyrez5Z _data]# cd /var/lib/docker/volumes/a5e71c3f49495c1b02fa559b92fb65ecc6dee0a1ce7fd3d2fa77b2dc1341e739/_data
      [root@iZwz908j8pbqd86doyrez5Z _data]# ls
      test.txt
      #验证完毕!
      
    6. 数据卷容器

      多个容器间的数据共享

      注意容器数据卷和数据卷容器的区别:

      • 容器的数据卷
      • 数据卷的容器:子容器挂载父容器(数据卷的容器)的数据,实现数据的同步
      #使用
      [root@iZwz908j8pbqd86doyrez5Z _data]# docker run -d -it --name docker01 arno/centos:1.0
      [root@iZwz908j8pbqd86doyrez5Z _data]# docker run -it --name docker02 --volumes-from docker01  arno/centos:1.0  #docker01的数据挂载到docker02上
      
      #验证
      [root@iZwz908j8pbqd86doyrez5Z _data]# docker attach docker01
      [root@5bd780fa7cad /]# ls
      bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volumen01
      dev  home  lib64  media       opt  root  sbin  sys  usr  volume02
      [root@5bd780fa7cad /]# cd volumen01
      [root@5bd780fa7cad volumen01]# touch test.txt
      [root@5bd780fa7cad volumen01]# ls
      test.txt
      [root@iZwz908j8pbqd86doyrez5Z _data]# docker attach docker02
      [root@56e0c6ac0d64 /]# ls
      bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volumen01
      dev  home  lib64  media       opt  root  sbin  sys  usr  volume02
      [root@56e0c6ac0d64 /]# cd volumen01
      [root@56e0c6ac0d64 volumen01]# ls
      test.txt
      
      #查看元数据
      [root@iZwz908j8pbqd86doyrez5Z _data]# docker inspect docker01
      "Mounts": [
      {
      "Type": "volume",
      "Name": "9c60002316aa06044c718bd6728a9c4e71865b3127773461f65a82354e26d70c",
      "Source": "/var/lib/docker/volumes/9c60002316aa06044c718bd6728a9c4e71865b3127773461f65a82354e26d70c/_data",
      "Destination": "volume02",
      "Driver": "local",
      "Mode": "",
      "RW": true,
      "Propagation": ""
      },
      {
      "Type": "volume",
      "Name": "e0584a1a806735c297b08629bb9ab4b1d419bbdc9a61fb5f526618a6096802b0",
      "Source": "/var/lib/docker/volumes/e0584a1a806735c297b08629bb9ab4b1d419bbdc9a61fb5f526618a6096802b0/_data",
      "Destination": "volumen01",
      "Driver": "local",
      "Mode": "",
      "RW": true,
      "Propagation": ""
      }
      ],
      
      [root@iZwz908j8pbqd86doyrez5Z _data]# docker inspect docker02
      "Mounts": [
      {
      "Type": "volume",
      "Name": "9c60002316aa06044c718bd6728a9c4e71865b3127773461f65a82354e26d70c",
      "Source": "/var/lib/docker/volumes/9c60002316aa06044c718bd6728a9c4e71865b3127773461f65a82354e26d70c/_data",
      "Destination": "volume02",
      "Driver": "local",
      "Mode": "",
      "RW": true,
      "Propagation": ""
      },
      {
      "Type": "volume",
      "Name": "e0584a1a806735c297b08629bb9ab4b1d419bbdc9a61fb5f526618a6096802b0",
      "Source": "/var/lib/docker/volumes/e0584a1a806735c297b08629bb9ab4b1d419bbdc9a61fb5f526618a6096802b0/_data",
      "Destination": "volumen01",
      "Driver": "local",
      "Mode": "",
      "RW": true,
      "Propagation": ""
      }
      ],
      
      #可以看到匿名挂载下,挂载的是同一个路径
      

      注:

      • 虽然挂载的时候有主次的关系,但是数据是互通的
      • 删除父容器,子容器内的数据还是能访问到,因为各个容器的数据卷真实主机地址的文件位置没有删
      • 主机->父容器->子容器,主机挂载数据卷到父容器,父容器作为数据卷容器对子容器挂载
      • 挂载的时候,本地一定会有对应的卷
  • 相关阅读:
    window.open打开新的独立页面
    域名如何添加解析?
    URL 链接中的 UTM参数何定义?
    学习总结【匿名函数,匿名自执行函数】
    CSS布局之Flex布局
    CSS布局之display: tables布局
    CSS里盒子模型中【margin垂直方向边界叠加】问题及解决方案
    Hibernate 事务管理
    Hibernate 二级缓存
    Hibernate c3p0的整合
  • 原文地址:https://www.cnblogs.com/Arno-vc/p/13673757.html
Copyright © 2011-2022 走看看