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": ""
    }
    ], #可以看到匿名挂载下,挂载的是同一个路径

    注:

    • 虽然挂载的时候有主次的关系,但是数据是互通的
    • 删除父容器,子容器内的数据还是能访问到,因为各个容器的数据卷真实主机地址的文件位置没有删
    • 主机->父容器->子容器,主机挂载数据卷到父容器,父容器作为数据卷容器对子容器挂载
    • 挂载的时候,本地一定会有对应的卷

Docker——容器数据卷的更多相关文章

  1. 『现学现忘』Docker基础 — 28、Docker容器数据卷介绍

    目录 1.什么是Docker容器数据卷 2.数据卷的作用 3.数据卷的使用 1.什么是Docker容器数据卷 Docker容器数据卷,即Docker Volume(卷). 当Docker容器运行的时候 ...

  2. docker 12 docker容器数据卷

    数据卷概念 ♣我们知道,当我们把一个运行中的容器关闭后,容器里的数据就没有了(如果你做了docker commit操作,数据会保留到新的镜像里面).所以我们就需要用容器数据卷把容器数据进行持久化储存. ...

  3. Docker容器数据卷

    ⒈Docker容器中数据如何持久化? ①通过commit命令使容器反向为镜像 ②以容器数据卷的方式将数据抽离 ⒉容器数据卷的作用? ①容器数据的持久化 ②容器间继承.共享数据 ⒊能干嘛? 卷就是目录或 ...

  4. Docker容器数据卷(七)

    Docker致力于: 将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的 容器之间希望有可能共享数据 Docker容器产生的数据,如果不通过docker co ...

  5. 5、docker容器数据卷: -v添加共享传递容器数据卷

    1.是什么 1.docker理念 先来看看Docker的理念:*  将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的*  容器之间希望有可能共享数据 2.保 ...

  6. Docker 容器数据卷(Data Volume)与数据管理

    卷(Volume)是容器中的一个数据挂载点,卷可以绕过联合文件系统,从而为Docker 提供持久数据,所提供的数据还可以在宿主机-容器或多个容器之间共享.通过卷,我们可以可以使修改数据直接生效,而不必 ...

  7. Docker容器数据卷-Volume详解

    Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker中称为数据卷(Data Volume).数据卷可以用来存储Docker应用的数据,也可以用来在Docker容器间进行数据共享.数据 ...

  8. docker学习笔记-04:docker容器数据卷

    一.容器数据卷是什么 1.为了保存docker容器运行时产生的数据,做数据的持久化,我们需要用到容器数据卷.因为如果不通过docker commit 生成新的镜像,那么当容器被删除时,数据自然就没有了 ...

  9. 『现学现忘』Docker基础 — 29、Docker容器数据卷的应用

    目录 1.验证容器和宿主机之间数据共享 2.容器停止退出后,主机修改后数据是否同步 3.带只读权限的挂载数据卷 1.验证容器和宿主机之间数据共享 通过上面的操作,接下来我们演示一下通过数据卷的挂载,实 ...

随机推荐

  1. docker错误处理——docker Job for docker.service failed because the control process exited with error code.

    (15条消息) docker Job for docker.service failed because the control process exited with error code._Hel ...

  2. windows server2012搭建邮箱服务器+客户端界面(hmailserver+afterlogic)+批量创建邮箱

    1.简介 由于需要较多邮箱,如果去注册需要很多的手机号码去验证,一个人不可能买一堆的手机号,所以自己搭建一个邮箱服务器可以大批量的创建自己的邮箱账号和收发邮件. 2.安装部署hmailserver 下 ...

  3. Keycloak 团队宣布他们正在弃用大多数 Keycloak 适配器,包括Spring Security和Spring Boot

    2月14日,Keycloak 团队宣布他们正在弃用大多数 Keycloak 适配器. 其中包括Spring Security和Spring Boot的适配器,这意味着今后Keycloak团队将不再提供 ...

  4. 根据经纬度坐标获得省市区县行政区划城市名称,自建数据库 java python php c# .net 均适用

    目录 步骤一.下载省市区边界数据 步骤二.解析CSV文件导入数据库 步骤三.在程序中根据坐标解析获得城市 在LBS应用中,根据坐标来解析获得对应是哪个城市是一个很常见的功能,比如App里面通过手机定位 ...

  5. Bootstrap提供的CDN服务标签与下载文档

    目录 1.引入Bootstrap提供的CDN服务 1.选择下载Bootstrap CDN 二:下载Bootstrap官方文档 1.进入Bootstrap官网,选择3版本中文档. 1.引入Bootstr ...

  6. python开启httpserver

  7. Gopher必读:HttpClient的两个坑位

    http是我们最常见的客户端/服务端传输协议,在golang中,默认的net/http包有一些坑位,需要调整以获得更加性能. 在golang程序中,我也遇到因为不合理使用 http client导致的 ...

  8. 【C# 线程】 volatile 关键字和Volatile类、Thread.VolatileRead|Thread.VolatileWrite 详细 完整

    overview 同步基元分为用户模式和内核模式 用户模式:Iterlocked.Exchange(互锁).SpinLocked(自旋锁).易变构造(volatile关键字.volatile类.Thr ...

  9. string 字符串的操作 大全类的使用

    Array.Sort(vv, string.CompareOrdinal); //ASCII排序 string[] words = { "The", "1quick&qu ...

  10. 服务器CPU很高-怎么办(Windbg使用坑点)

    最近,碰到了一个线上CPU服务器很高的问题,并且也相当紧急,接到这个任务后,我便想到C#性能分析利器,Windbg. 终于在折腾半天之后,找出了问题,成功解决,这里就和大家分享一下碰到的问题. 问题1 ...