美文网首页
docker入门(4)--数据卷管理

docker入门(4)--数据卷管理

作者: 随意的ID | 来源:发表于2018-10-29 14:41 被阅读0次

    任何有意义的应用都会产生或者使用一些数据。而容器本身是无状态的。我们使用数据卷(volumes)来解决这个问题。数据卷允许容器使用,产生和修改数据。数据卷比容器拥有更高等级的生命周期,当使用volume的容器结束时,volume依然存在。

    1. 创建和挂载数据卷

    1.1 修改容器内数据

    在正式开始介绍数据卷之前,我们先看看直接在容器内进行数据修改操作会发生什么。
    在容器内新增一个文件:

    docker container run --name demo \
        alpine /bin/sh -c 'echo "This is a test" > sample.txt'
    

    容器与基础镜像进行比较:

    docker container diff demo
    

    结果类似如下:

    A /sample.txt
    

    当停止并移除这个容器后,你新建的sample.txt文件也会随之删除,再也无法继续使用。

    1.2 创建数据卷

    如下命令创建一个名为my-data的数据卷:
    docker volume create my-data
    默认的数据卷驱动称之为本地驱动,它将数据存储在本机的文件系统上。如果你需要了解数据卷的详细信息,可使用docker volume inspect命令进行核查。
    docker volume inspect my-data
    得到类似如下结果:

    [
        {
            "CreatedAt": "2018-10-29T13:58:22+08:00",
            "Driver": "local",
            "Labels": {},
            "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
            "Name": "my-data",
            "Options": {},
            "Scope": "local"
        }
    ]
    

    tips:docker还支持以插件形式使用的,第三方的一些数据卷驱动,例如:云存储,NFS,SDN(软件定义网络)存储。只需要在创建数据卷时,使用--driver参数进行指定即可。

    1.3 挂载数据卷

    当我们创建了数据卷之后,就可以挂载使用它了。

    docker container run --name test -it \
        > -v my-data:/data alpine /bin/sh
    

    启动并进入容器后,执行如下命令,在容器内新建文件:

    / # cd /data
    /data # echo "some data" > data.txt
    /data # echo "some more data" > data1.txt
    /data # exit
    

    回到主机,我们在/var/lib/docker/volumes/my-data/_data/目录下,可以看到:

    [root@node2 ~]# ll /var/lib/docker/volumes/my-data/_data/
    total 8
    -rw-r--r-- 1 root root 15 Oct 29 14:13 data1.txt
    -rw-r--r-- 1 root root 10 Oct 29 14:13 data.txt
    [root@node2 ~]# cat /var/lib/docker/volumes/my-data/_data/data.txt 
    some data
    [root@node2 ~]# cat /var/lib/docker/volumes/my-data/_data/data1.txt 
    some more data
    

    接下来,我们直接在主机的数据卷目录下创建文件,然后新启动一个容器,挂载这个数据卷,看看是什么效果。

    [root@node2 ~]# cd /var/lib/docker/volumes/my-data/_data/
    [root@node2 _data]# echo "This file we create on the host" > host_data.txt
    [root@node2 _data]# docker container rm test 
    test
    [root@node2 _data]# docker container run --name test2 -it \
    > -v my-data:/app/data \
    > centos:7 /bin/bash
    Unable to find image 'centos:7' locally
    7: Pulling from library/centos
    aeb7866da422: Pull complete 
    Digest: sha256:67dad89757a55bfdfabec8abd0e22f8c7c12a1856514726470228063ed86593b
    Status: Downloaded newer image for centos:7
    [root@9015fe11c4dd /]# ls /app/data
    data.txt  data1.txt  host_data.txt
    [root@9015fe11c4dd /]# cat /app/data/host_data.txt 
    This file we create on the host
    

    1.4 删除数据卷

    我们可以使用docker volume rm来删除数据卷。特别提示:由于该操作是不可逆的,当你确认数据卷已经进行了备份,或者该数据卷确实没有其他用途的时候,你可以进行删除操作。但是,如果该数据卷如果还在使用中,是无法进行删除的。

    [root@node2 _data]# docker volume rm my-data 
    Error response from daemon: remove my-data: volume is in use - [9015fe11c4dd6450b2587e5b36979b64796541e7d67656003d8decae1fcc735e]
    [root@node2 _data]# docker container ls -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                  NAMES
    9015fe11c4dd        centos:7            "/bin/bash"              8 minutes ago       Exited (0) 4 minutes ago                          test2
    78a0c2a1ac94        alpine              "/bin/sh"                3 days ago          Exited (0) 3 days ago                             sample
    ce3d8b9082c5        alpine              "/bin/sh"                3 days ago          Exited (0) 3 days ago                             upbeat_kirch
    48a55ac2ee94        nginx:alpine        "nginx -g 'daemon of…"   3 days ago          Up 3 days                  0.0.0.0:8080->80/tcp   nginx-test
    0f8cf054c73d        alpine              "echo 'hello world'"     3 days ago          Exited (0) 3 days ago                             angry_colden
    f5ed73fec895        hello-world         "/hello"                 3 days ago          Exited (0) 3 days ago                             dreamy_leakey
    [root@node2 _data]# docker container rm 9015fe11c4dd
    9015fe11c4dd
    [root@node2 _data]# docker volume rm my-data 
    my-data
    

    2. 在容器之间分享数据

    有些时候,容器之间是需要进行数据交互的。有可能A容器产生的数据,将用于给B容器进行读取使用,但为了避免冲突(同时对文件的修改),我们可以在挂载数据卷的时候设置一些读写权限。

    [root@node2 ~]# docker volume create shared-data
    shared-data
    # 创建一个写文件的容器
    [root@node2 ~]# docker container run --name writer -it \
    > -v shared-data:/data \
    > alpine /bin/sh
    / # cd /data
    /data # touch data-from-writer.txt
    /data # ls
    data-from-writer.txt
    # 创建一个只能读的容器,并挂载shared-data数据卷
    [root@node2 ~]# docker container run --name only-reader -it \
    > -v shared-data:/data:ro \
    > centos:7 /bin/bash
    [root@cf058c0af6af /]# cd /data/
    [root@cf058c0af6af data]# touch data.txt
    touch: cannot touch 'data.txt': Read-only file system
    

    3. 使用主机目录进行挂载

    除了数据卷,我们还可以将主机上的某个目录直接挂载到容器内,如下:

    docker container run -d -v /my-web:/usr/share/nginx/html -p 8080:80 nginx:alpine
    

    4. 在Dockerfile中定义数据卷

    对于一些应用,例如数据库,我们肯定是需要进行数据持久化的,但是面对不同的使用者和不同的使用环境,我们的官方镜像是如何在面对不同环境时,主动的去定义一个数据卷呢?答案是:在Dockerfile中就定义好数据卷,这样生成的镜像在启动时,就会自动的创建数据卷。

    # 列出目前已有的volume
    [root@node2 ~]# docker volume ls
    DRIVER              VOLUME NAME
    local               shared-data
    # 创建一个mongo容器
    [root@node2 ~]# docker container run -d --name my-mongo mongo:3.7
    e65ac72b9c3fc7abdcc05121b55c87543baccc3b27bf17be6ad0ec1212211141
    # 查看自动添加的volume
    [root@node2 ~]# docker volume ls
    DRIVER              VOLUME NAME
    local               065a116f6ef50622aa3e1f674f81cc61d13e4618b6f726b5fd77f4813fcc5e84
    local               10242f5b75f1ba88e1e2abdbb2cc874887f4181353ea62ca6f2c6735c32b0e7b
    local               shared-data
    

    我们也可以使用docker image inspect命令来审查镜像的数据卷相关配置。

    [root@node2 ~]# docker image inspect \
    > --format='{{json .ContainerConfig.Volumes}}' \
    > mongo:3.7 | jq
    {
      "/data/configdb": {},
      "/data/db": {}
    }
    

    上面的结果显示,mongo:3.7这个image会创建两个volume。
    我们也可以通过docker container inspect命令来审查当前运行容器的数据卷挂载情况。

    [root@node2 ~]# docker container inspect --format '{{json .Mounts}}' my-mongo | jq
    [
      {
        "Type": "volume",
        "Name": "065a116f6ef50622aa3e1f674f81cc61d13e4618b6f726b5fd77f4813fcc5e84",
        "Source": "/var/lib/docker/volumes/065a116f6ef50622aa3e1f674f81cc61d13e4618b6f726b5fd77f4813fcc5e84/_data",
        "Destination": "/data/configdb",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
      },
      {
        "Type": "volume",
        "Name": "10242f5b75f1ba88e1e2abdbb2cc874887f4181353ea62ca6f2c6735c32b0e7b",
        "Source": "/var/lib/docker/volumes/10242f5b75f1ba88e1e2abdbb2cc874887f4181353ea62ca6f2c6735c32b0e7b/_data",
        "Destination": "/data/db",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
      }
    ]
    

    5. 关于使用volume还是bind mounts(本机目录)的建议

    首先请参考这几篇官方文章:
    Manage data in Docker
    Use volumes
    Use bind mounts
    以下内容为谷歌翻译:

    卷的好处:
    • 在多个运行容器之间共享数据。如果未显式创建它,则会在第一次将其装入容器时创建卷。当该容器停止或被移除时,该卷仍然存在。多个容器可以同时安装相同的卷,可以是
      读写也可以是只读。仅在您明确删除卷时才会删除卷。
    • 当Docker主机不能保证具有给定的目录或文件结构时。Volumes可帮助您将Docker主机的配置与容器运行时分离。
    • 如果要将容器的数据存储在远程主机或云提供程序上,而不是本地存储。
    • 当您需要备份,还原或将数据从一个Docker主机迁移到另一个Docker主机时,卷是更好的选择。您可以使用卷停止容器,然后备份卷的目录(例如/var/lib/docker/volumes/<volume-name>)。
    绑定挂载的好处:

    通常,您应该尽可能使用卷。绑定适用于以下类型的用例:

    • 将配置文件从主机共享到容器。这就是Docker默认通过/etc/resolv.conf从主机安装到每个容器中来为容器提供DNS解析的方式 。
    • 在Docker主机上的开发环境和容器之间共享源代码或构建工件。例如,您可以将Maven target/ 目录安装到容器中,每次在Docker主机上构建Maven项目时,容器都可以访问重建的工件。
      如果您以这种方式使用Docker进行开发,您的生产Dockerfile会将生产就绪工件直接复制到映像中,而不是依赖于绑定装载。
    • 当Docker主机的文件或目录结构保证与容器所需的绑定装载一致时。

    6. 关于使用-v参数还是--mount参数的建议

    docker新用户,我们建议使用--mount,但是这个参数只能在docker 17.06版本以后才可以使用。
    --mount参数使用如下:

    $ docker service create \
         --mount 'type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path>,"volume-opt=o=addr=<nfs-address>,vers=4,soft,timeo=180,bg,tcp,rw"'
        --name myservice \
        <IMAGE>
    

    --mount与-v的区别:

    As opposed to bind mounts, all options for volumes are available for both --mount and -v flags.
    When using volumes with services, only --mount is supported.

    相关文章

      网友评论

          本文标题:docker入门(4)--数据卷管理

          本文链接:https://www.haomeiwen.com/subject/pejbtqtx.html