赞
踩
我们都知道,通过Docker可以将我们的软件运行环境和基于运行环境开发的软件打包成镜像,而镜像运行伴随着容器,内部数据文件的生命周期也同容器的生命周期。但是在我们实际的应用中,我们是希望能够将一些数据持久化的。
就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!
Docker容器产生的数据,如果不通过docker commit 生成新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行不通的!
所以我们希望能有一种技术,可以实现数据共享。于是容器卷技术变孕育而生。
为了能保存在Docker中的数据,我们就可以使用卷!让数据挂载到我们本地(可持久化保存数据的磁盘)!这样数据就不会因为容器删除而丢失了!
作用:
卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
特点:
总结起来就是:通过数据卷实现了容器数据的持久化,以及容器间的数据共享。
既然我们知道了使用数据卷有很多优点,那么我们怎么使用呢?
挂载:
# 命令
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,具体我们会在后面博文中说到。
[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]#
[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 指令来给镜像添加一个或多个数据卷
注意镜像名称不能有大写
[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:给镜像命名。命令的最后有一个
.
不能省略。
制作镜像成功。
[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 /]#
[root@jiangnan home]# docker inspect 1fabdfdf4803
这样也能实现挂载。新建文件在本地和容器中都能看到。
我们都知道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挂载到了本地的同一个目录下,所以他们都共享了本地目录中的资源。这种方式间接实现了容器间的数据共享。
# 匿名挂载
-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
命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。
前面的例子中,我们创建了镜像mycentos,我们以此为模板,运行容器mycentos01,mycentos02,mycentos03
我们来测试下,容器间传递共享
后台运行。
[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 /]#
--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]#
[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创建的文件。
其实就是实现了数据共享,任何一个容器中创建的文件或修改,在其他关联的容器中都可以同步更新。
即使删除了其中一些容器,其他容器依然可以看到文件的更新状态。
得出结论:
容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。
存储在本机的文件会一直保留!
docker volume ls
用于查看和维护数据卷。
我的微信公众号先已开通,各位小伙伴们可以关注我,后面文章会进行同步,方便查看。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。