前言
学习了docker命令后,接下来要进行学习的就是docker中比较核心的知识:容器数据卷、dockerFile以及docker网络,在这里将学习docker基础的过程记录下来
一、容器数据卷
docker的理念是将我们写好的应用和环境进行打包成为一个镜像。
1. 什么是容器数据卷?
如果我们都将数据放在容器中,将容器删除以后,数据就会丢失。因此就引出了将数据持久化的需求。因此就有了容器之间数据共享的技术:将Docker容器中产生的数据同步到本地。这就是容器数据卷的技术:也叫目录的挂载,将容器内的目录挂载到本机上面。
图解:
容器数据卷的一个好处是哪怕此时容器没有启动,但是要修改容器内的数据只需在本地操作即可,同时容器间也可以进行数据的共享。
2. 通过命令使用数据卷
使用方法: 使用命令来进行挂载:-v
docker run -it -v 主机目录:容器目录 # 测试: # 运行centos容器,并将容器中的/home目录挂载到主机中的/home/ceshi目录下 [root@VM-16-16-centos home]# docker run -it -v /home/ceshi:/home centos /bin/bash ...按快捷键Ctrl + P + Q退出容器... # 查看当前正在运行的容器 [root@VM-16-16-centos ceshi]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b46ad200daed centos "/bin/bash" 20 seconds ago Up 19 seconds pensive_cartwright # 查看容器的元数据 [root@VM-16-16-centos ceshi]# docker inspect b46ad200daed 此处省略其它数据... "Mounts": [ { "Type": "bind", # 绑定的形式 "Source": "/home/ceshi", # 主机内地址 "Destination": "/home", # docker容器内的地址 "Mode": "", "RW": true, "Propagation": "rprivate" } ], 此处省略其它数据...
查看数据卷
在可以进行挂载卷以后,可以通过相应的命令来查看数据卷的挂载信息
docker volume [参数] # 可选参数 Commands: create # 创建一个数据卷 inspect # 查看数据卷的元数据 ls # 查看所有的数据卷 rm # 移除一个或多个数据卷
匿名挂载
匿名挂载就是我们在进行挂载时不写主机内路径,只写容器内路径,docker会自动帮我们在主机生成一个目录用于容器的数据挂载
-v 容器内路径 # 例如: # 查看所有数据卷信息 [root@VM-16-16-centos home]# docker volume ls DRIVER VOLUME NAME # 以下就是匿名挂载 local 4bf18cbb2a6128f80fcb499803fc40fd4205255766da919c1dfa0e86accf1944 local 4f417a0068e19f84c0f26a287ad1fde01cc07897d6be80122b7c21f574d78e02 local 7e51a5b64ea902b4035769321b4156dbe9c118f5e32a3e5c70cf8c23968d5db8 local 33119b40b12d49c1d325d8630c8cec5aeb6ceb3c225691e32d6aa407399a4b58
像这样VOLUME_NAME
中没有具体的名字,只有一串地址值的挂载方式就叫匿名挂载
具名挂载
同理,与匿名挂载相反,具名挂载就是在挂载前通过-v 卷名:容器内路径
来进行挂载
-v 卷名:容器内路径 # 例如: # 将centos容器的/home/ceshi目录下的内容挂载到主机,并且将数据卷的名称设置为juming-centos [root@VM-16-16-centos home]# docker run -d -it -v juming-centos:/home/ceshi centos ddfcb311e27b8bd3e592c89ef0f453e72d3f9031f2b7b8975553b946a14841a8 # 查看所有的挂载列表 [root@VM-16-16-centos home]# docker volume ls DRIVER VOLUME NAME local db38f0d2d4fd98997ae86acfcf096cfff6b39230963aeb323da14d1e942e2d08 local juming-centos
但是此时只知道将容器内的数据卷挂载到了主机,具体挂载到了哪个位置则需要使用inspect
来查看
# 通过具体的数据卷名称来查看数据卷的元数据 [root@VM-16-16-centos home]# docker volume inspect juming-centos [ { "CreatedAt": "2021-11-11T21:11:11+08:00", "Driver": "local", "Labels": null, # 本机具体的挂载位置 "Mountpoint": "/var/lib/docker/volumes/juming-centos/_data", "Name": "juming-centos", "Options": null, "Scope": "local" } ]
所有docker容器内部的数据卷,在没有指定主机内的挂载目录时都是在/var/lib/docker/volumes/容器名称/_data
位置进行挂载
因为通过具名挂载可以使我们很方便的找到一个数据卷,因此在大多数情况下都是使用具名挂载
3. 通过Dockerfile使用数据卷
Dockerfile就是用来构建docker镜像的构建文件,通过这个dockerfile脚本可以生成镜像。因为镜像是层级结构,因此Dockerfile脚本文件也具备层级结构,脚本文件中的每一层都是一个命令
创建dockerfile文件,名字可以随便,建议为dockerfile,文件中的内容指令全部为大写,文件中的每一个命令都是镜像中的一层
在这里写一个测试文件来进行测试
# 编辑dockerfile文件 [root@VM-16-16-centos testDockerfile]# vim dockerfile # 查看编辑的文件内容 [root@VM-16-16-centos testDockerfile]# cat dockerfile FROM centos VOLUME ["volume01","volume02"] CMD echo "----------end----------" CMD /bin/bash # 在输出文件内容没有问题时,开始根据dockerfile构建docker镜像 [root@VM-16-16-centos testDockerfile]# docker build -f dockerfile -t centos:1.0 . Sending build context to Docker daemon 2.048kB # 基础的镜像 Step 1/4 : FROM centos ---> 5d0da3dc9764 # 通过VOLUME进行挂载 Step 2/4 : VOLUME ["volume01","volume02"] ---> Running in 02e35dd76b93 Removing intermediate container 02e35dd76b93 ---> fa6b31173f3a Step 3/4 : CMD echo "----------end----------" ---> Running in 4508cdfca653 Removing intermediate container 4508cdfca653 ---> 75c26eb52f3f Step 4/4 : CMD /bin/bash ---> Running in c836f8ca91a1 Removing intermediate container c836f8ca91a1 ---> 30a7c5c2798f Successfully built 30a7c5c2798f Successfully tagged centos:1.0 # 根据dockerfile构建好docker镜像后查看 [root@VM-16-16-centos testDockerfile]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE # 这里就是我们刚才通过dockerfile构建的镜像 centos 1.0 30a7c5c2798f About a minute ago 231MB tomcat latest b0e0b0a92cf9 3 weeks ago 680MB centos latest 5d0da3dc9764 8 weeks ago 231MB mysql 8.0.13 102816b1ee7d 2 years ago 486MB # 启动自己写的容器 [root@VM-16-16-centos testDockerfile]# docker run -it 30a7c5c2798f /bin/bash
此时的数据卷一定在本机有一个同步的目录,在dockerfile中VOLUME这一行中没有指定数据卷的名称,为匿名挂载
# 在容器内跳转到volume01目录下 [root@6e08f4a4abbd /]# cd volume01 # 在该目录下新建container.txt文件 [root@6e08f4a4abbd volume01]# touch container.txt # 在不结束容器运行的前提下退出容器 [root@6e08f4a4abbd volume01]# read escape sequence # 查看当前容器的元数据 [root@VM-16-16-centos testDockerfile]# docker inspect 6e08f4a4abbd ...... 此处省略其他数据 ...... "Mounts": [ { "Type": "volume", "Name": "a54af2a118121fbff85d951429b4d4de69c8a7f8840a8cd8202b192c9bad9806", "Source": "/var/lib/docker/volumes/a54af2a118121fbff85d951429b4d4de69c8a7f8840a8cd8202b192c9bad9806/_data", "Destination": "volume02", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "6acd9a7ec3ffdaa8ccd728d6da31338fadff11042b5e052c9c35cfdee0f4cc4e", "Source": "/var/lib/docker/volumes/6acd9a7ec3ffdaa8ccd728d6da31338fadff11042b5e052c9c35cfdee0f4cc4e/_data", "Destination": "volume01", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], ... 此处省略其他数据 ...
测试刚才在容器中新建的文件是否同步到了主机
这种方式就是数据卷的挂载,未来在构建自己的镜像时会经常使用这种挂载方式。
数据卷容器
这这里启动三个容器来进行测试,通过刚才自己写的镜像来启动
# 启动第一个容器并命名为docker01 [root@VM-16-16-centos _data]# docker run -it --name docker01 centos:1.0 [root@837e1ade25ff /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var volume01 volume02
[root@VM-16-16-centos _data]# docker run -it --name docker02 --volumes-from docker01 centos:1.0 [root@f40031fc1017 /]# ls -l total 56 lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin drwxr-xr-x 5 root root 360 Nov 13 01:55 dev drwxr-xr-x 1 root root 4096 Nov 13 01:55 etc drwxr-xr-x 2 root root 4096 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 4096 Sep 15 14:17 lost+found drwxr-xr-x 2 root root 4096 Nov 3 2020 media drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt drwxr-xr-x 2 root root 4096 Nov 3 2020 opt dr-xr-xr-x 120 root root 0 Nov 13 01:55 proc dr-xr-x--- 2 root root 4096 Sep 15 14:17 root drwxr-xr-x 11 root root 4096 Sep 15 14:17 run lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin drwxr-xr-x 2 root root 4096 Nov 3 2020 srv dr-xr-xr-x 13 root root 0 Nov 13 01:55 sys drwxrwxrwt 7 root root 4096 Sep 15 14:17 tmp drwxr-xr-x 12 root root 4096 Sep 15 14:17 usr drwxr-xr-x 20 root root 4096 Sep 15 14:17 var # 在创建的docker02容器中也有了挂载的数据卷 drwxr-xr-x 2 root root 4096 Nov 13 01:51 volume01 drwxr-xr-x 2 root root 4096 Nov 13 01:51 volume02
现在进入docker01容器
# 查看当前正在运行的容器 [root@VM-16-16-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 822ae9cfcc8d centos:1.0 "/bin/sh -c /bin/bash" About a minute ago Up About a minute docker02 837e1ade25ff centos:1.0 "/bin/sh -c /bin/bash" 56 minutes ago Up 56 minutes docker01 6e08f4a4abbd 30a7c5c2798f "/bin/bash" 2 hours ago Up 2 hours youthful_thompson # 进入到容器docker02中 [root@VM-16-16-centos ~]# docker attach 822ae9cfcc8d # 跳转到docker02的volume01目录下 [root@822ae9cfcc8d /]# cd volume01 # 查看当前目录下的文件,发现此时docker02容器的volume01的目录下有在docker01中volume01目录中创建的文件 [root@822ae9cfcc8d volume01]# ls docker01.txt
图解:
在测试成功两个容器相互挂载后,现在再增加一个是否仍然可以挂载呢?
现在创建第三个容器docker03容器挂载到docker01容器上
[root@VM-16-16-centos ~]# docker run -it --name docker03 --volumes-from docker01 centos:1.0 [root@6b7b0023d7c9 /]# cd volume01 [root@6b7b0023d7c9 volume01]# ls docker01.txt [root@6b7b0023d7c9 volume01]# touch docker03.txt [root@6b7b0023d7c9 volume01]# [root@VM-16-16-centos ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6b7b0023d7c9 centos:1.0 "/bin/sh -c /bin/bash" 36 seconds ago Up 35 seconds docker03 822ae9cfcc8d centos:1.0 "/bin/sh -c /bin/bash" 18 minutes ago Up 18 minutes docker02 837e1ade25ff centos:1.0 "/bin/sh -c /bin/bash" About an hour ago Up About an hour docker01 6e08f4a4abbd 30a7c5c2798f "/bin/bash" 2 hours ago Up 2 hours youthful_thompson [root@VM-16-16-centos ~]# docker attach 837e1ade25ff [root@837e1ade25ff volume01]# ls docker01.txt docker03.txt
此时容器docker02和docker03此时都挂载到了docker01上,那么又会产生一个问题,就是当我们将docker01容器删除或停止以后,docker02和docker03容器中的数据是否仍然存在?接着进行测试
测试结果发现,删除docker01容器后依旧可以访问挂载到docker01中的文件,因此可以发现,在docker 容器挂载是双向拷贝的概念,类似于vue中的v-model双向数据绑定,可以实现两个容器的数据同步。
图解
结论:容器之间配置信息的传递,数据容器的生命周期一直持续到没有容器使用为止。一旦持久化到了本地,哪怕把所有的容器删除掉,这个时候本地的数据同样是不会删除的