Docker 容器数据卷(六)

文章介绍了Docker数据卷的概念和作用,强调了数据卷在容器间共享和数据持久化的重要性。通过示例展示了如何使用命令行创建和挂载数据卷,以及在Dockerfile中声明数据卷。同时,讨论了匿名和具名挂载的区别,并介绍了数据卷容器的概念,用于多容器间的数据共享。
摘要由CSDN通过智能技术生成

一、什么是容器数据卷

docker 的理念回顾:

        将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够持久化的!就好比,你安装一个 MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!

        所以我们希望容器之间有可能可以共享数据,Docker 容器产生的数据,如果不通过 Docker commit 生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行不通的!

        为了能保存数据在 Docker 中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除而丢失了!

作用:

        卷就是目录或者文件,存在一个或者多个容器中,由 docker 挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性。

        卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此 Docker 不会在容器删除时删除其挂载的数据卷。

特点:

        1、数据卷可在容器之间共享或重用数据

        2、卷中的更改可以直接生效

        3、数据卷中的更改不会包含在镜像的更新中

        4、数据卷的生命周期一直持续到没有容器使用它为止

二、使用数据卷

容器中直接使用命令来添加

        1、启动容器并挂载

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

# 测试
[root@localhost home]# docker run -it -v /home/ceshi:/home centos /bin/bash

# 查看数据卷是否挂载成功 
docker inspect 容器id

        2、测试容器和宿主机之间数据共享,可以发现,在容器中创建的文件会在宿主机中看到。

         3、测试容器停止退出后,主机修改数据是否会同步

# 1、停止容器

# 2、在宿主机修改文件,增加些内容

# 3、启动刚才的容器

# 4、查看对应的文件是否发生变化,结果是发生了变化

使用 docker 安装 mysql

# 1、搜索镜像
[root@localhost home]# docker search mysql
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   14320     [OK]       

# 2、拉取镜像
[root@localhost home]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Pull complete 
93619dbc5b36: Pull complete 
99da31dd6142: Pull complete 
626033c43d70: Pull complete 
37d5d7efb64e: Pull complete 
ac563158d721: Pull complete 
d2ba16033dad: Pull complete 
0ceb82207cd7: Pull complete 
37f2405cae96: Pull complete 
e2482e017e53: Pull complete 
70deed891d42: Pull complete 
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

# 3、启动容器 -e 环境变量!mysql 的数据应该不丢失!先体验下 -v 挂载卷! 参考官方文档
[root@localhost home]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
b6a5895fbab7a5acfd332bf8b2f2f541e6fbff5d425a597983b7877ae7641c60

# 4、使用本地的数据库连接工具连接测试一下,并创建一个数据库 test

# 5、查看本地的 /home/mysql 目录,可以看到我们刚刚建立的 test 数据库在本地存储着
[root@localhost home]# cd /home/mysql/data/
[root@localhost 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

# 6、删除 mysql 容器,然后发现远程连接失败!可以看到我们刚刚建立的 test 数据库还在本地存储着
[root@localhost data]# docker rm -f mysql01
mysql01
[root@localhost 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




使用 DockerFile 来添加数据卷

        DockerFile 是用来构建 Docker 镜像的构建文件,是由一些列命令和参数构成的脚本。我们在这里先体验下,后面我们会详细讲解 DockerFile

# 1、我们在宿主机 /home 目录下新建一个 docker_volume_test 文件夹
[root@localhost home]# mkdir docker_volume_test

# 说明:在编写 DockerFile 文件中使用 VOLUME 指令来给镜像添加一个或多个数据卷
# 例如:VOLUME["/dataVolume1","/dataVolume2","/dataVolume3"]
# 出于可移植和分享的考虑,我们之前使用的 -v 主机目录:容器目录 这种方式不能够直接在 DockerFile 中实现。因为宿主机目录是依赖于特定宿主机的,并不能够保证在所有宿主机上都存在这样的特定目录

# 2、编写 DockerFile 文件
[root@localhost docker_volume_test]# pwd
/home/docker_volume_test
[root@localhost docker_volume_test]# vim dockerfile
[root@localhost docker_volume_test]# cat dockerfile 
FROM centos
VOLUME ["dataVolume1","dataVolume2"]
CMD echo "------end-----"
CMD /bin/bash

# 3、build 后生成镜像,获得一个新镜像 xhf_centos
# 注意最后有个.
[root@localhost docker_volume_test]# docker build -f /home/docker_volume_test/dockerfile -t xhf_centos .
[+] Building 0.5s (5/5) FINISHED                                                                              docker:default
 => [internal] load .dockerignore                                                                                       0.2s
 => => transferring context: 2B                                                                                         0.0s
 => [internal] load build definition from dockerfile                                                                    0.2s
 => => transferring dockerfile: 185B                                                                                    0.1s
 => [internal] load metadata for docker.io/library/centos:latest                                                        0.0s
 => [1/1] FROM docker.io/library/centos                                                                                 0.0s
 => exporting to image                                                                                                  0.0s
 => => exporting layers                                                                                                 0.0s
 => => writing image sha256:9a63d60a258f85e3bfe65ad6c8ac1e53a280fae5356f1bcec650bfa66e919989                            0.0s
 => => naming to docker.io/library/xhf_centos  
# 查看我们生成的镜像
[root@localhost docker_volume_test]# docker images
REPOSITORY            TAG                IMAGE ID       CREATED         SIZE
xhf_centos            latest             9a63d60a258f   22 months ago   231MB
centos                latest             5d0da3dc9764   22 months ago   231MB

# 4、启动容器
[root@localhost docker_volume_test]#  docker run -it 9a63d60a258f /bin/bash
[root@0f3404705e21 /]# ls -l
total 0
lrwxrwxrwx.   1 root root   7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x.   2 root root   6 Jul 19 07:47 dataVolume1  # 数据卷目录
drwxr-xr-x.   2 root root   6 Jul 19 07:47 dataVolume2  # 数据卷目录
drwxr-xr-x.   5 root root 360 Jul 19 07:47 dev
drwxr-xr-x.   1 root root  66 Jul 19 07:47 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  2021 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. 257 root root   0 Jul 19 07:47 proc
dr-xr-x---.   2 root root 162 Sep 15  2021 root
drwxr-xr-x.  11 root root 163 Sep 15  2021 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 Jul 12 07:05 sys
drwxrwxrwt.   7 root root 171 Sep 15  2021 tmp
drwxr-xr-x.  12 root root 144 Sep 15  2021 usr
drwxr-xr-x.  20 root root 262 Sep 15  2021 var

# 问题:通过上述步骤,容器内的卷目录地址就已经知道了,但是对应的主机目录地址在哪里呢?

# 5、我们在数据卷中新建一个文件
[root@0f3404705e21 dataVolume1]# pwd
/dataVolume1
[root@0f3404705e21 dataVolume1]# touch dataTest.java
[root@0f3404705e21 dataVolume1]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 07:50 dataTest.java

# 6、查看下这个容器的信息
[root@localhost ~]# docker inspect 0f3404705e21
// ......
"Mounts": [
            {
                "Type": "volume",
                "Name": "fdd0a9596867bda543cefd22df9632cef624c9bfa6ffe9daa13fd042b0d98aee",
                "Source": "/var/lib/docker/volumes/fdd0a9596867bda543cefd22df9632cef624c9bfa6ffe9daa13fd042b0d98aee/_data",
                "Destination": "dataVolume1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "0fe1ff905e66aef43d7db6502fd5d98e9cf67ca83c8c1ab6614fe72da2ea84cd",
                "Source": "/var/lib/docker/volumes/0fe1ff905e66aef43d7db6502fd5d98e9cf67ca83c8c1ab6614fe72da2ea84cd/_data",
                "Destination": "dataVolume2",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
// ........

# 7、查看我们刚才创建的文件信息
[root@localhost ~]# cd /var/lib/docker/volumes/fdd0a9596867bda543cefd22df9632cef624c9bfa6ffe9daa13fd042b0d98aee/_data
[root@localhost _data]# ls
dataTest.java
[root@localhost _data]# 

三、匿名和具名挂载

# 匿名挂载
# -v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx

# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume 维护
docker volume ls

# 具名挂载
# -v 卷名:/容器内路径
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx

# 查看挂载的路径
[root@localhost data]# docker volume inspect nginxconfig
[
    {
        "CreatedAt": "2023-07-18T02:13:38-07:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data",
        "Name": "nginxconfig",
        "Options": null,
        "Scope": "local"
    }
]

# 怎么判断挂载的是卷名而不是本机目录名?
# 不是 / 开始就是卷名,是 / 开始就是目录名

# 改变文件的读写权限
# ro: readonly
# rw: readwrite
# 指定容器对我们挂载出来的内容的读写权限
docker run -d -P --name nginx03 -v nginxconfig:/etc/nginx:ro nginx
docker run -d -P --name nginx04 -v nginxconfig:/etc/nginx:rw nginx

四、数据卷容器

        命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。

        我们使用上一步自定义的镜像:xhf_centos 为模板,并运行容器 docker01docker02docker03,因为他们都默认具有容器卷。

        1、先启动一个父容器 docker01,然后在 dataVolume1 中新增文件 docker01.txt,如下所示:

退出不停止:ctrl+P+Q

        2、创建 docker02 docker03 让他们都继承 docker01,使用 --volumes-from 标签

# 启动 docker02
[root@621e0c81ba67 dataVolume2]# [root@localhost ceshi]# docker run -it --name docker02 --volumes-from docker01 xhf_centos
[root@85789dab892c /]# cd /dataVolume2
[root@85789dab892c dataVolume2]# ls
docker01.txt
[root@85789dab892c dataVolume2]# touch docker02.txt
[root@85789dab892c dataVolume2]# ls
docker01.txt  docker02.txt

# 启动 docker03
[root@85789dab892c dataVolume2]# [root@localhost ceshi]# docker run -it --name docker03 --volumes-from docker01 xhf_centos
[root@35d6d33de63c /]# cd /dataVolume2
[root@35d6d33de63c dataVolume2]# ls
docker01.txt  docker02.txt
[root@35d6d33de63c dataVolume2]# touch docker03.txt
[root@35d6d33de63c dataVolume2]# ls
docker01.txt  docker02.txt  docker03.txt

        3、回到 docker01 发现可以看到 docker02 docker03  添加的文件。

[root@localhost ~]# docker attach docker01
[root@621e0c81ba67 dataVolume2]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 08:05 docker01.txt
-rw-r--r--. 1 root root 0 Jul 19 08:08 docker02.txt
-rw-r--r--. 1 root root 0 Jul 19 08:09 docker03.txt

        4、删除 docker01 容器并且在 docker02 容器添加文件,然后看 docker03 容器还能不能访问。

[root@localhost ~]# docker rm -f docker01
docker01

[root@localhost ~]# docker attach docker02
[root@85789dab892c dataVolume2]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 08:05 docker01.txt
-rw-r--r--. 1 root root 0 Jul 19 08:08 docker02.txt
-rw-r--r--. 1 root root 0 Jul 19 08:09 docker03.txt

[root@85789dab892c dataVolume2]# touch docker02-update.txt
[root@85789dab892c dataVolume2]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 08:05 docker01.txt
-rw-r--r--. 1 root root 0 Jul 19 08:15 docker02-update.txt
-rw-r--r--. 1 root root 0 Jul 19 08:08 docker02.txt
-rw-r--r--. 1 root root 0 Jul 19 08:09 docker03.txt

# 此时已经切换到 docker03 容器了,使用ctrl+p+q 
[root@35d6d33de63c dataVolume2]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 08:05 docker01.txt
-rw-r--r--. 1 root root 0 Jul 19 08:15 docker02-update.txt
-rw-r--r--. 1 root root 0 Jul 19 08:08 docker02.txt
-rw-r--r--. 1 root root 0 Jul 19 08:09 docker03.txt

        5、删除 docker02 ,测试 docker03 还能不能访问。答案是可以访问的。

[root@localhost ~]# docker rm -f docker02
docker02
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                                     NAMES
35d6d33de63c   xhf_centos   "/bin/sh -c /bin/bash"   9 minutes ago   Up 9 minutes                                             docker03
[root@localhost ~]# docker attach docker03 
[root@35d6d33de63c dataVolume2]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 08:05 docker01.txt
-rw-r--r--. 1 root root 0 Jul 19 08:15 docker02-update.txt
-rw-r--r--. 1 root root 0 Jul 19 08:08 docker02.txt
-rw-r--r--. 1 root root 0 Jul 19 08:09 docker03.txt
[root@35d6d33de63c dataVolume2]# touch docker03_update.txt

        6、新建 docker04 继承 docker03,然后再删除 docker03,看下是否可以访问!

[root@localhost ~]# docker run -it --name docker04 --volumes-from docker03 xhf_centos

[root@fd19bc431b37 /]# cd /dataVolume2
[root@fd19bc431b37 dataVolume2]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 08:05 docker01.txt
-rw-r--r--. 1 root root 0 Jul 19 08:15 docker02-update.txt
-rw-r--r--. 1 root root 0 Jul 19 08:08 docker02.txt
-rw-r--r--. 1 root root 0 Jul 19 08:09 docker03.txt
-rw-r--r--. 1 root root 0 Jul 19 08:19 docker03_update.txt

# 切换目录 ctrl+p+q
[root@localhost ~]# docker rm -f docker03
docker03
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED              STATUS              PORTS                                     NAMES
fd19bc431b37   xhf_centos   "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute                                             docker04
[root@localhost ~]# docker attach docker04
[root@fd19bc431b37 dataVolume2]# ls -l
total 0
-rw-r--r--. 1 root root 0 Jul 19 08:05 docker01.txt
-rw-r--r--. 1 root root 0 Jul 19 08:15 docker02-update.txt
-rw-r--r--. 1 root root 0 Jul 19 08:08 docker02.txt
-rw-r--r--. 1 root root 0 Jul 19 08:09 docker03.txt
-rw-r--r--. 1 root root 0 Jul 19 08:19 docker03_update.txt

结论:

        容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。存储在本机的文件则会一直保留!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐的小三菊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值