本文最后更新于 319 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com
docker数据卷存储
一.docker存储卷概述
1.什么是存储卷
存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。
2.在容器创建测试文件,而后在宿主机查看器存储路径
如下图所示,我们在容器创建测试文件,在宿主机查找时发现了2个文件路径。
我们需要进入的是包含"merged"的路径哟~因为它才是真正存储容器的位置呢。
3.默认情况下,容器在宿主机存储的数据会随着容器的生命周期而消亡
如下图所示,当我们删除容器时,那也意味着在宿主机存储的数也随之删除。
二.在宿主机中上传测试代码,观察容器是否能够正常提供服务
1.安装依赖包环境
[root@docker201.oldboyedu.com ~]# yum -y install unzip
2.创建测试的nginx容器
[root@docker201.oldboyedu.com ~]# docker run -it -d -p 80:80 nginx:1.20.1
3.将软件包上传到docker的宿主机目录
[root@docker201.oldboyedu.com /var/lib/docker/overlay2/c8f3eaf1cba887b7370d1dd86521989a76f5d642a76c3b790111b42b05d0212e/merged/usr/share/nginx/html]# unzip xiaoniaofeifei.zip
4.测试软件包部署是否生效。
[root@docker201.oldboyedu.com ~]# docker logs -f -n 5 3e755e41ce6f
温馨提示:
你知道为什么使用"docker logs"能在终端查看到日志吗?
想知道原因就得进到容器内查看"/var/log/nginx"目录哟~
5.课堂练习
请思考除了使用上面的方式是否还有其它方式实现容器的代码更新呢?
温馨提示:
(1)使用"docker container cp"指令,直接将代码拷贝到指定容器的指定目录;
(2)使用存储卷;
三.基于存储卷的方式实现代码的更新
1.创建挂载源代码的目录及测试数据
如下图所示,将代码上传到指定的目录并解压。
2.创建容器时挂载宿主机目录
[root@docker201.oldboyedu.com ~]# docker container run -d -p 8888:80 -v /oldboy/code:/usr/share/nginx/html nginx:1.20.1
[root@docker201.oldboyedu.com ~]# docker container run -d -p 9999:80 -v /oldboy/code:/usr/share/nginx/html nginx:1.20.1
温馨提示:
相比之前的方法,如果想要多个容器使用同一份数据,需要将同一份数据拷贝到多个不同的容器内部,而使用存储卷的方式,则无需拷贝多份数据啦。
3.尝试修改宿主机代码,观察两个容器的变化
如下图所示,根本无需重启容器,只需更改宿主机器的代码即可。
4.多个容器使用存储卷的原理
如下图所示,展示了多个容器使用同一个宿主机绝对路径的挂载原理。
5.删除容器时宿主机的数据并不会被删除
如下图所示,当我们删除容器时,发现并不会一同删除挂载的存储卷。换句话说,就是不会删除宿主机的文件。
四.基于存储卷挂载(例如保存MySQL的数据)
1.创建存储卷
[root@docker201.oldboyedu.com ~]# docker volume create oldboyedu
温馨提示:
存储卷的默认存储路径位于"/var/lib/docker/volumes"
2.使用存储卷挂载
[root@docker201.oldboyedu.com ~]# docker container run -it -d -p 8888:80 -v oldboyedu:/usr/share/nginx/html nginx:1.20.1
3.删除容器时,存储卷的数据并不会丢失
如下图所示,当我们删除容器时,存储卷中的数据并不会丢失!
4.固定的卷名,也可以实现数据共享
数据卷的最强大的功能就是持久化数据,我们可以将多个容器挂载到同一个数据卷,从而实现了数据的共享。但有的容器并不支持挂载同一个目录,比如MySQL多实例的情况,如果指定的数据目录存在文件,则数据库会初始化失败哟。
如下图所示,本篇案例演示的都是基于本地卷进行挂载,我们可以借助插件的方式帮咱们实现远程的数据挂载哟;
5.关于存储卷的其它说明
如果存储卷下面没有数据,它会将容器指定目录下的文件持久化到存储卷的数据目录下。
如果存储卷下面有数据,它会把存储卷的数据目录挂载到容器的指定目录。
五.跟某个容器挂载所有相同的卷
1.创建一个测试卷
[root@docker201.oldboyedu.com ~]# ll /oldboy/code/
总用量 232
-rw-r--r-- 1 root root 15329 8月 2 2014 2000.png
-rw-r--r-- 1 root root 51562 8月 2 2014 21.js
-rw-r--r-- 1 root root 254 8月 2 2014 icon.png
drwxr-xr-x 2 root root 102 8月 8 2014 img
-rw-r--r-- 1 root root 3059 6月 13 13:58 index.html
drwxr-xr-x 7 root root 171 6月 13 15:39 kod
-rw-r--r-- 1 root root 63008 8月 2 2014 sound1.mp3
-rw-r--r-- 1 root root 91014 6月 13 13:25 xiaoniaofeifei.zip
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker run -d -p 80:80 -v /oldboy/code:/usr/share/nginx/html nginx:1.20.1
220264c94b193fa8f4eab215d4561e0f7664fed9f4eb92ebba101c4a89be200d
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
220264c94b19 nginx:1.20.1 "/docker-entrypoint.…" 4 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp priceless_euler
[root@docker201.oldboyedu.com ~]#
2.再次创建一个测试卷
[root@docker201.oldboyedu.com ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
220264c94b19 nginx:1.20.1 "/docker-entrypoint.…" 4 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp priceless_euler
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker run -d -p 8888:80 --volumes-from 220264c94b19 nginx:1.20.1
c4b4058ab33f7c40e04177c8b0a1872789780dd08f4d227eceda6eb7ffbc35f2
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c4b4058ab33f nginx:1.20.1 "/docker-entrypoint.…" 2 seconds ago Up 2 seconds 0.0.0.0:8888->80/tcp, :::8888->80/tcp great_grothendieck
220264c94b19 nginx:1.20.1 "/docker-entrypoint.…" 16 seconds ago Up 16 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp priceless_euler
[root@docker201.oldboyedu.com ~]#
3.测试结果
如下图所示,分别访问两个容器暴露的端口,返回的结果却是一样的。
六.持久化数据到随机卷(适合保存变化的数据,例如日志文件)
1.创建随机卷来持久化容器的目录下的数据
如下图所示,我们可以直接指定nginx的日志目录分别挂载不同的存储卷上。
温馨提示:
静态的文件,可以共享。比如代码文件。
变化的文件,不能共享,需要单独保存。比如日志文件。
2.删除容器
如下图所示,当我们删除容器时,数据并未丢失哟。
温馨提示:
下面的只是一个测试案例,不用在乎软连接,我只是为了测试一下效果。
3.课堂练习
只允许启动一个nginx容器,要求如下:
(1)访问8888端口,出现nginx默认的欢迎首页,要求使用存储卷使用;
(2)访问8889端口,出现"小鸟飞飞",要求使用存储卷使用;
(3)访问8890端口,出现容器主机名,IP地址;
温馨提示:
实现效果如下图所示。
七.课堂练习案例多种解法
1.解法一
(1)本地创建测试代码
[root@docker201.oldboyedu.com ~]# ll /oldboy/code/
总用量 232
-rw-r--r-- 1 root root 15329 8月 2 2014 2000.png
-rw-r--r-- 1 root root 51562 8月 2 2014 21.js
-rw-r--r-- 1 root root 254 8月 2 2014 icon.png
drwxr-xr-x 2 root root 102 8月 8 2014 img
-rw-r--r-- 1 root root 3059 6月 13 13:58 index.html
drwxr-xr-x 7 root root 171 6月 13 15:39 kod
-rw-r--r-- 1 root root 63008 8月 2 2014 sound1.mp3
-rw-r--r-- 1 root root 91014 6月 13 13:25 xiaoniaofeifei.zip
[root@docker201.oldboyedu.com ~]#
(2)挂载本地目录到容器(但请不要覆盖nginx容器默认的代码文件,因为我们是要访问2个站点目录)
[root@docker201.oldboyedu.com ~]# docker run -d -p 8888:80 -p 9999:9999 -v /oldboy/code:/oldboyedu/code nginx:1.20.1
(3)进入容器生成配置文件(由于没有vi命令,因此我们可以借助echo或者cat生成nginx的配置文件)
[root@docker201.oldboyedu.com ~]# docker exec -it e634dfcc6248 bash
root@e634dfcc6248:/# ls /oldboyedu/code/
2000.png 21.js icon.png img index.html kod sound1.mp3 xiaoniaofeifei.zip
root@e634dfcc6248:/#
root@e634dfcc6248:/etc/nginx/conf.d# cat xiaoniao.conf
server {
listen 9999;
server_name localhost;
location / {
root /oldboyedu/code;
index index.html index.htm;
}
}
root@e634dfcc6248:/etc/nginx/conf.d#
(4)对nginx的配置文件进行测试
root@e634dfcc6248:/etc/nginx/conf.d# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@e634dfcc6248:/etc/nginx/conf.d#
(5)重启nginx的配置文件
[root@docker201.oldboyedu.com ~]# docker container restart e634dfcc6248
温馨提示:
有小伙伴可能会质疑,为啥我不用nginx的reload指令呢?的确进入到容器进行reload是是一个可行的方案哟,但不是所有的服务都得reload,比如tomcat就不支持reload指令哟。
综上所诉,我们上面演示的方法更加通用。
2.解法二
(1)本地创建测试代码
[root@docker201.oldboyedu.com ~]# ll /oldboy/code/
总用量 232
-rw-r--r-- 1 root root 15329 8月 2 2014 2000.png
-rw-r--r-- 1 root root 51562 8月 2 2014 21.js
-rw-r--r-- 1 root root 254 8月 2 2014 icon.png
drwxr-xr-x 2 root root 102 8月 8 2014 img
-rw-r--r-- 1 root root 3059 6月 13 13:58 index.html
drwxr-xr-x 7 root root 171 6月 13 15:39 kod
-rw-r--r-- 1 root root 63008 8月 2 2014 sound1.mp3
-rw-r--r-- 1 root root 91014 6月 13 13:25 xiaoniaofeifei.zip
[root@docker201.oldboyedu.com ~]#
(2)挂载本地目录到容器(但请不要覆盖nginx容器默认的代码文件,因为我们是要访问2个站点目录)
[root@docker201.oldboyedu.com ~]# docker run -d -p 8888:80 -p 9999:9999 -v /oldboy/code:/oldboyedu/code nginx:1.20.1
(3)在宿主机上生成配置文件
[root@docker201.oldboyedu.com ~]# vim xiaoniao.conf
[root@docker201.oldboyedu.com ~]#
[root@docker201.oldboyedu.com ~]# cat xiaoniao.conf
server {
listen 9999;
server_name localhost;
location / {
root /oldboyedu/code;
index index.html index.htm;
}
}
[root@docker201.oldboyedu.com ~]#
(3)将宿主机的配置文件拷贝到其他电脑上
[root@docker201.oldboyedu.com ~]# docker container cp xiaoniao.conf c5f11694d7d9:/etc/nginx/conf.d
(4)重启容器
如下图所示,重启容器后,可以使用浏览器访问到相应的数据哟~
3.解法三
[root@docker201.oldboyedu.com ~]# docker run -d -p 8888:80 -p 9999:9999 -v /root/xiaoniao.conf:/etc/nginx/conf.d/xiaoniao.conf -v /oldboy/code:/oldboyedu/code nginx:1.20.1
温馨提示:
理解了前面的两种解法后,第三种解法自然就明白了。
八.扩展内容
数据卷挂在还支持权限配置,比如说rw代表读写,ro代表只读.
案例1:
docker container run -it -v /oldboyedu/data/:/oldboyedu-linux:ro -it -w /oldboyedu-linux --rm alpine
案例2:
docker container run -it -v /oldboyedu/data/:/oldboyedu-linux:rw -it -w /oldboyedu-linux --rm alpine
案例3:(挂在磁盘)
docker container run -it --device=/dev/sdc:/dev/oldboyedu-sdc --rm alpine
推荐阅读:
https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from
https://docs.docker.com/engine/reference/commandline/run/#add-host-device-to-container---device
九.小彩蛋
1.添加硬盘不重启就可以识别
for i in `seq 0 2` ; do echo "- - -" > /sys/class/scsi_host/host$i/scan;done
温馨提示:
使用"lsblk"命令查看磁盘即可.