zoukankan      html  css  js  c++  java
  • docker容器的数据管理之一(数据卷)

    两个需求

    持久化:

    Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。
    比如redis,我们虽然利用把数据存储在内存中来提高读写速度(内存的速度比硬盘快很多),但是为了防止数据丢失,redis提供了两种持久化:rdb和aof文件。

    docker持久化的方式是什么?

    数据共享:

    容器作为一个个集装箱是相对独立的,那么容器之间如果需要读写同一个数据块,该如何处理?

    容器数据卷

    docker的镜像是由多个只读的文件系统叠加在一起形成的。当我们在我启动一个容器的时候,docker会加载这些只读层并在这些只读层的上面(栈顶)增加一个读写层。这时如果修改正在运行的容器中已有的文件,那么这个文件将会从只读层复制到读写层。该文件的只读版本还在,只是被上面读写层的该文件的副本隐藏。当删除docker,或者重新启动时,之前的更改将会消失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。

    为了很好的实现数据保存和数据共享,Docker提出了Volume这个概念,简单的说就是绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。又被称作数据卷。

    容器数据卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性。
    卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

    添加数据卷:使用命令

    docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

    运行以下命令会在容器的根目录下创建containerVolume目录,同时还会在宿主机的根目录下创建centosVolume目录:

    docker run -it -v /centosVolume:/containerVolume centos /bin/bash

    容器与宿主机实现数据共享

    此时,处于宿主机和容器的这两个目录,增删改查等操作都是同步的

    1.在宿主机中的目录新建一个文件centosfile,并编辑:

     此时查看容器中目录与文件:

     无论是新建的文件,还是文件的内容,都已同步至容器中。

    2.在容器中编辑centosfile(>是覆盖,>>是追加):

     此时查看宿主机中文件:

    可见在容器中的修改也会同步到宿主机。

    此时使用docker inspect 查看容器:

    "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/centosVolume",
                    "Destination": "/containerVolume",
                    "Mode": "",
                    "RW": true,
                    "Propagation": "rprivate"
                }
            ],

    RW为true,表示此时的权限是可读可写。

    控制权限的命令操作(:ro)

    docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
    
    #ro表示read only

    此时使用docker inspect 查看容器:

     "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/centosVolume",
                    "Destination": "/containerVolume",
                    "Mode": "ro",
                    "RW": false,
                    "Propagation": "rprivate"
                }
            ],

    此时mode为ro,RW为false,这是什么意思?

    1.在宿主机中的目录新建一个文件ROfile,并编辑:

     此时查看容器中目录与文件:

     

     此时,在宿主机中的修改,依然可以同步至容器。

    2.在容器中编辑ROfile

     提示是只读的文件系统,那可以新建文件吗?

    可见,在使用设置权限的方式添加数据卷后,在宿主机中的修改依然可以同步至容器,但在容器中只读不可写。

    容器停止后,是否还同步宿主机的数据

    停掉容器后,在宿主机的centosVolume目录下新建文件containerStop并编辑:

    重启容器并进入交互,查看容器的containerVolume目录下的文件与内容:

    所以,只要在创建容器时挂载了数据卷,无论容器是否运行,都会同步宿主机的数据。

    添加数据卷:使用DockerFile

    Dockerfile是什么?

    Dockerfile是docker中镜像的描述文件,说的直白点就是描述了镜像文件到底是由什么东西一步步构成的。

    比如tomcat的DockerFIle:https://github.com/docker-library/tomcat/blob/8438be7c4c8434b617903ea5a478441ae04572c1/8.5/jdk8/openjdk/Dockerfile

    如何使用Dockerfile添加数据卷?

    1.根目录下新建mydocker文件夹,在该文件夹中新建编辑一个dockerfile文件

    # volume test
    FROM centos
    VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
    CMD echo "finished,--------success1"
    CMD /bin/bash

    # 解释
      继承centos镜像
      添加两个容器卷
      打印success
      shell  /bin/bash 

    2.根据dockerfile文件build一个新镜像

    docker build -f /mydocker/dockerfile -t nick/centos .

    [root@izbp13m488196e5hna361rz mydocker]# docker build -f /mydocker/dockerfile -t nick/centos .
    Sending build context to Docker daemon  2.048kB
    Step 1/4 : FROM centos
     ---> 300e315adb2f
    Step 2/4 : VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
     ---> Running in b826770c140a
    Removing intermediate container b826770c140a
     ---> d75d106ff106
    Step 3/4 : CMD echo "finished,--------success1"
     ---> Running in 9dc4873e4b86
    Removing intermediate container 9dc4873e4b86
     ---> 5c55449c9438
    Step 4/4 : CMD /bin/bash
     ---> Running in e627bd6e1bf1
    Removing intermediate container e627bd6e1bf1
     ---> bc5060004e4f
    Successfully built bc5060004e4f
    Successfully tagged nick/centos:latest

    可见build的过程是严格按照dockerfile中的描述一步步执行的,所以镜像分了很多层,最后的.表示当前目录。

    3.根据这个镜像run一个容器

    发现,在容器的根目录下有dataVolumeContainer1和dataVolumeContainer2两个数据卷

    [root@izbp13m488196e5hna361rz mydocker]# docker run -it nick/centos /bin/bash
    [root@c4598aeb6ea4 /]# ls
    bin  dataVolumeContainer1  dataVolumeContainer2  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

    宿主机中对应的默认路径在哪?

    在使用命令-v添加数据卷的时候,同时指定了宿主机和容器内的目录:

    docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

    而上述步骤中dockerfile的方式,只写明了容器内的卷目录地址,那么对应的宿主机的目录地址在哪?

    使用docker inspect 容器id ,查看容器信息:

     "Mounts": [
                {
                    "Type": "volume",
                    "Name": "4170885a6bba2913a4ef435783d102418407cfae17f2fa1a10fdef53efa97cc3",
                    "Source": "/var/lib/docker/volumes/4170885a6bba2913a4ef435783d102418407cfae17f2fa1a10fdef53efa97cc3/_data",
                    "Destination": "/dataVolumeContainer1",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                },
                {
                    "Type": "volume",
                    "Name": "5a4ba4ccb27fc79523dedda5f9f1af6ac305380d8af6355b7afab005d3ec9a9a",
                    "Source": "/var/lib/docker/volumes/5a4ba4ccb27fc79523dedda5f9f1af6ac305380d8af6355b7afab005d3ec9a9a/_data",
                    "Destination": "/dataVolumeContainer2",
                    "Driver": "local",
                    "Mode": "",
                    "RW": true,
                    "Propagation": ""
                }
            ],

    所以,宿主机中对应的默认路径就是:/var/lib/docker/volumes

  • 相关阅读:
    SpringCloud组件---Ribbon
    SpringCloud组件---Eureka
    tomcat及Jetty远程调试debug
    mysql 删除重复数据
    mysql执行SQL语句时报错:[Err] 3
    线程池原理剖析
    上限下限
    线程池Executors、Callable与Future的应用
    spring获取bean(自定义工具类)
    java.util.concurrent.Exchanger应用范例
  • 原文地址:https://www.cnblogs.com/xulan0922/p/14299341.html
Copyright © 2011-2022 走看看