【Docker篇】深度理解容器数据卷,匿名挂载和具名挂载,数据卷容器

数据容器卷

1. 什么是容器数据卷

我们都知道,通过Docker可以将我们的软件运行环境和基于运行环境开发的软件打包成镜像,而镜像运行伴随着容器,内部数据文件的生命周期也同容器的生命周期。但是在我们实际的应用中,我们是希望能够将一些数据持久化的。

就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!

Docker容器产生的数据,如果不通过docker commit 生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行不通的!

所以我们希望能有一种技术,可以实现数据共享。于是容器卷技术变孕育而生。

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

在这里插入图片描述

作用

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

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

特点

  1. 数据卷可在容器之间共享或重用数据
  2. 卷中的更改可以直接生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

总结起来就是:通过数据卷实现了容器数据的持久化,以及容器间的数据共享。

2. 使用数据卷

既然我们知道了使用数据卷有很多优点,那么我们怎么使用呢?

方式一:我们使用命令直接添加。

挂载

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

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

-v就是将我们的宿主机和容器进行挂载。

我们可以通过docker inspect 容器id查看是否挂载成功,主要看Mounts部分。

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

Source是对应虚拟机的路径。Destination是对应容器内的路径。

测试

我们先在虚拟机的/home目录下新建一个hello.txt文件,看能否同步到容器内的/home目录下。

在这里插入图片描述

发现:在宿主机上创建的文件也容器内也能看到。

我们在容器内将文件进行修改。看能否宿主机上的文件也跟着修改。

在这里插入图片描述

发现:修改容器内的文件,宿主机的文件也被修改了,数据实现了双向同步

上面我们说了,数据卷挂载是为了实现数据持久化,防止删库跑了,那么能不能做到呢?

我们将容器停止。

在这里插入图片描述

发现:虽然停止了容器,但是本地的hello.txt依然存在。数据持久化实现了。

这个时候如果我们再次修改本地文件,当我们重启容器之后,发现容器内的文件跟我们本地修改过的文件保持同步,真正实现了数据同步、共享。

在这里插入图片描述

方式二:使用Dockerfile

这里给大家简单写一个Dockerfile,具体我们会在后面博文中说到。

  1. 我们现在宿主机/home目录下新建一个文件夹/tomcat-volume文件夹
[root@jiangnan home]# mkdir tomcat-volume
[root@jiangnan home]# ll
total 12
-rw-r--r-- 1 root root   12 Feb 22 22:53 hello.txt
drwxr-xr-x 4 root root 4096 Feb 22 23:16 tomcat
drwxr-xr-x 2 root root 4096 Feb 23 19:25 tomcat-volume   # 新建一个tomcat-volume文件夹
[root@jiangnan home]# 
  1. 编写一个Dockerfile
[root@jiangnan ~]# cd /home/tomcat-volume/
[root@jiangnan tomcat-volume]# vi Dockerfile
[root@jiangnan tomcat-volume]# cat Dockerfile 
FROM centos
VOLUME ["/volume1","/volume2"]
CMD echo "-------end------"
CMD /bin/bash
[root@jiangnan tomcat-volume]# 

DockerFile文件中使用 VOLUME 指令来给镜像添加一个或多个数据卷

  1. 生成镜像,命名为mycentos

注意镜像名称不能有大写

[root@jiangnan tomcat-volume]# docker build -f /home/tomcat-volume/Dockerfile -t mycentos . 
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : VOLUME ["/volume1","/volume2"]
 ---> Running in a9dcdbdb111e
Removing intermediate container a9dcdbdb111e
 ---> 6811c813ce47
Step 3/4 : CMD echo "-------end------"
 ---> Running in 92c7e1ef5987
Removing intermediate container 92c7e1ef5987
 ---> e58a5176b91d
Step 4/4 : CMD /bin/bash
 ---> Running in 3f1310167f22
Removing intermediate container 3f1310167f22
 ---> 91f16e4a921e
Successfully built 91f16e4a921e
Successfully tagged mycentos:latest
[root@jiangnan tomcat-volume]# 

-f:指定Dockerfile。-t:给镜像命名。命令的最后有一个.不能省略。

在这里插入图片描述

制作镜像成功。

  1. 启动刚才制作的镜像并查看目录结构
[root@jiangnan tomcat-volume]# docker run -it 91f16e4a921e /bin/bash
[root@1fabdfdf4803 /]# ls -l
total 56
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Feb 23 11:38 dev
drwxr-xr-x   1 root root 4096 Feb 23 11:38 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
drwxr-xr-x  12 root root 4096 Sep 15 14:17 usr
drwxr-xr-x  20 root root 4096 Sep 15 14:17 var
drwxr-xr-x   2 root root 4096 Feb 23 11:38 volume1  # 数据卷目录
drwxr-xr-x   2 root root 4096 Feb 23 11:38 volume2  # 数据卷目录
[root@1fabdfdf4803 /]# 
  1. 查看本地挂载目录
[root@jiangnan home]# docker inspect 1fabdfdf4803

在这里插入图片描述

这样也能实现挂载。新建文件在本地和容器中都能看到。

3. 实战

我们都知道tomcat部署项目文件需要放在webapps下才可以访问,但是每次文件更新我们都需要启动tomcat吗?显然不用,我们只需要将webapps目录挂在到我们本地某个目录下,将所需文件放进去,他会自动同步到tomcat的webapps目录下。

[root@jiangnan home]# docker run -d -v /home/tomcat/webapps:/usr/local/tomcat/webapps -p 8081:8080 --name tomcat01 tomcat

启动完之后,我将事先准备好的项目放到宿主机的/home/tomcat/webapps目录下。

在这里插入图片描述

发现:容器中确实有了。

我们访问看看效果,我上面用8081端口映射了容器的8080端口,所以需要用8081端口访问。

在这里插入图片描述

没有问题。

在实际的应用中,我们还可以将一些配置文件进行挂载,这样修改起来更加方便。

如何容器间数据共享

我们上面还说到容器之间进行数据共享,这个怎么做呢?

我们再启动一个tomcat03,同样挂载到本地的/home/tomcat/webapps下。暴露端口8082。

[root@jiangnan webapps]# docker run -d -v /home/tomcat/webapps:/usr/local/tomcat/webapps -p 8082:8080 --name tomcat03 tomcat
9aacff8773bc1ee92acc2c598fd497cde18e9c44192a9942906ae16c5e0ead2e
[root@jiangnan webapps]# 

不做任何操作直接访问。

在这里插入图片描述
在这里插入图片描述

也没有问题。

因为两个tomcat挂载到了本地的同一个目录下,所以他们都共享了本地目录中的资源。这种方式间接实现了容器间的数据共享。

4. 匿名挂载和具名挂载

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

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

[root@jiangnan webapps]# docker run -d -p 80:80 --name nginx01 -v /etc/nginx nginx
d270788d32058ffbd9dbbd9a98133f42b05dbf3881d25b8d482d36c12c0279d5
[root@jiangnan webapps]# docker volume ls
DRIVER    VOLUME NAME
local     4b595f9bdc43c312f982c594a3f3087920e08d53b9f9e090779509d14f0f4638

# 查看挂载的路径
[root@jiangnan webapps]# docker volume inspect 4b595f9bdc43c312f982c594a3f3087920e08d53b9f9e090779509d14f0f4638
[
    {
    
    
        "CreatedAt": "2022-02-22T23:49:12+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/4b595f9bdc43c312f982c594a3f3087920e08d53b9f9e090779509d14f0f4638/_data",
        "Name": "4b595f9bdc43c312f982c594a3f3087920e08d53b9f9e090779509d14f0f4638",
        "Options": null,
        "Scope": "local"
    }
]
[root@jiangnan webapps]# 
# 具名挂载
-v 卷名:/容器内路径
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx

[root@jiangnan webapps]# docker run -d -p 81:80 --name nginx02 -v nginxconfig:/etc/nginx nginx
6e3a6b44c49c5b656c9a0dc838c66c2614537b4b00503b8a567140d1fde4adfb

# 查看挂载的路径
[root@jiangnan webapps]# docker volume inspect nginxconfig
[
    {
    
    
        "CreatedAt": "2022-02-22T23:50:48+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data",
        "Name": "nginxconfig",
        "Options": null,
        "Scope": "local"
    }
]
[root@jiangnan webapps]# 

具名和匿名就是给我们的挂载卷是不是要起个名字。显然具名挂载更方便。

怎么判断挂载的是卷名而不是本机目录名?

不是/开始就是卷名,是/开始就是目录名

改变文件的读写权限
ro: readonly
rw: readwrite

指定容器对我们挂载出来的内容的读写权限

docker run -d -p 81:80 --name nginx02 -v nginxconfig:/etc/nginx:ro nginx
docker run -d -p 81:80 --name nginx02 -v nginxconfig:/etc/nginx:rw nginx  

5. 数据卷容器

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

前面的例子中,我们创建了镜像mycentos,我们以此为模板,运行容器mycentos01,mycentos02,mycentos03

我们来测试下,容器间传递共享

  1. 启动父容器mycentos01

后台运行。

[root@jiangnan tomcat-volume]# docker run -d -it --name mycentos01 mycentos
[root@9ba991b24352 /]# ls -l
total 56
lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x   5 root root  360 Feb 23 11:50 dev
drwxr-xr-x   1 root root 4096 Feb 23 11:50 etc
drwxr-xr-x   2 root root 4096 Nov  3  2020 home
drwxr-xr-x  12 root root 4096 Sep 15 14:17 usr
drwxr-xr-x  20 root root 4096 Sep 15 14:17 var
drwxr-xr-x   2 root root 4096 Feb 23 11:50 volume1
drwxr-xr-x   2 root root 4096 Feb 23 11:50 volume2
[root@9ba991b24352 /]# 
  1. 创建mycentos02和mycentos03,让他们继承mycentos01

--volumes-from

[root@jiangnan tomcat-volume]# docker run -d -it --name mycentos02 --volumes-from mycentos01 centos
c804e323d49c7203809069ed413c692e637adc02f3797957f1b6537c7d1bbf5c

[root@jiangnan tomcat-volume]# docker run -d -it --name mycentos03 --volumes-from mycentos01 centos
2306661ebddd801550a20765ce7dc123cdff7d60cfebe3dc6287a8d659cf58cd
[root@jiangnan tomcat-volume]# 
  1. 现在我们进入mycentos03并创建文件。
[root@jiangnan tomcat-volume]# docker exec -it 2306661ebddd /bin/bash
[root@2306661ebddd /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume1  volume2
[root@2306661ebddd /]# cd volume1
[root@2306661ebddd volume1]# ls
[root@2306661ebddd volume1]# touch mycentos03.txt
[root@2306661ebddd volume1]# 

然后我们进入到mycentos01和mycentos02中,也能看到mycentos03创建的文件。
在这里插入图片描述

其实就是实现了数据共享,任何一个容器中创建的文件或修改,在其他关联的容器中都可以同步更新。

即使删除了其中一些容器,其他容器依然可以看到文件的更新状态。

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

6. 总结

  1. 容器数据卷其实就是实现了容器数据持久化操作的技术。
  2. 通过数据卷实现了容器数据的持久化,以及容器间的数据共享。
  3. 在启动容器时可以通过命令挂载容器卷,也可以在Dockerfile来添加。
  4. 不是/开始就是卷名,是/开始就是目录名。具名挂载有名字,匿名挂载没有名字。
  5. docker volume ls用于查看和维护数据卷。
  6. 挂载数据卷的容器,称之为数据卷容器。
  7. 容器间的数据共享本质是挂载到了本地的目录,实现了数据共享
  8. 数据卷的生命周期一直持续到没有容器使用它为止。
  9. 存储在本机的文件会一直保留。

在这里插入图片描述
我的微信公众号先已开通,各位小伙伴们可以关注我,后面文章会进行同步,方便查看。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45842494/article/details/123098436
今日推荐