本章主要学习容器数据卷的知识,通过绑定容器卷,到达主机跟容器内数据共通的目的。同时添加了mysql的实战练习,巩固操作。容器卷挂载方式、挂载查看、数据卷容器等知识。
容器数据卷
什么是容器数据卷
docker的理念回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失! 需求:数据可以持久化
MySQL,容器删了,删库跑路! 需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上!
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的
使用数据卷
方式一: 直接使用命令来挂载 -v 双向绑定
docker run -it -v 主机目录:容器内目录
# 测试
[root@iZwz909zuxxmim3sok3i3qZ home]# docker run -it -v /home/test:/home centos /bin/bash
# 记得到宿主机里,查看宿主机 home目录下 多出了test 即容器内的home目录将会跟宿主机下的home/test目录同步
[root@iZwz909zuxxmim3sok3i3qZ home]# ls
next-node-demo queqian.js test
# 查看镜像是否有挂载 用inspect
[root@iZwz909zuxxmim3sok3i3qZ home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5de1ee947a26 centos "/bin/bash" 3 minutes ago Up 3 minutes pensive_wu
[root@iZwz909zuxxmim3sok3i3qZ home]# docker inspect 5de1ee947a26
打印出来找到mounts ,这里意味着容器内的home目录将会跟宿主机下的home/test目录同步资源。且这时候test文件以及home文件下都没有任何文件
测试同步
# 这时候在test或者home下新建一个文件 这是在home下
[root@5de1ee947a26 home]# touch test.js
# 然后在主机test文件夹下有了这个文件 数据同步了
[root@iZwz909zuxxmim3sok3i3qZ test]# ls
test.js
# 容器停止后 主机的文件上还是保留着数据
[root@iZwz909zuxxmim3sok3i3qZ test]# docker kill 5de1ee947a26
5de1ee947a26
[root@iZwz909zuxxmim3sok3i3qZ test]# ls
test.js
# 这时候修改test.js
[root@iZwz909zuxxmim3sok3i3qZ test]# vim test.js #esc 后:wq 保存退出
# 重新启动该容器并且查看文件
[root@iZwz909zuxxmim3sok3i3qZ home]# docker start 5de1ee947a26
5de1ee947a26
[root@iZwz909zuxxmim3sok3i3qZ home]# docker attach 5de1ee947a26
[root@5de1ee947a26 /]# cd /home
[root@5de1ee947a26 home]# ls
test.js
[root@5de1ee947a26 home]# cat test.js
hello linux update!
# 查看到容器内挂载的文件确实被修改了 哪怕容器当时已经停止
好处:我们以后修改只需要在本地修改即可,容器内会自动同步。
实战:安装MySQL
思考:MySQL的数据持久化数据
# 下载mysql镜像
[root@iZwz909zuxxmim3sok3i3qZ test]# docker pull mysql:5.7
# 运行容器的时候做数据挂载! 安装启动mysql,需要配置密码的
# 官方测试 docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 运行
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器命名
[root@iZwz909zuxxmim3sok3i3qZ 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
验证
下载SQLyog,输入公网ip 端口 以及刚刚的密码 测试链接。会得到下图
# 查看本机的mysql
[root@iZwz909zuxxmim3sok3i3qZ home]# ls
mysql next-node-demo queqian.js test
[root@iZwz909zuxxmim3sok3i3qZ home]# cd mysql
[root@iZwz909zuxxmim3sok3i3qZ mysql]# ls
conf data
[root@iZwz909zuxxmim3sok3i3qZ mysql]# cd data/
[root@iZwz909zuxxmim3sok3i3qZ data]# ls
auto.cnf client-key.pem ib_logfile1 private_key.pem sys
ca-key.pem ib_buffer_pool ibtmp1 public_key.pem
ca.pem ibdata1 mysql server-cert.pem
client-cert.pem ib_logfile0 performance_schema server-key.pem
SQL上创建一个数据库
# 再次查看本机的data文件夹
[root@iZwz909zuxxmim3sok3i3qZ data]# ls
auto.cnf client-key.pem ib_logfile1 private_key.pem sys
ca-key.pem ib_buffer_pool ibtmp1 public_key.pem test
ca.pem ibdata1 mysql server-cert.pem
client-cert.pem ib_logfile0 performance_schema server-key.pem
即使把容器删除了 但是数据是不会消失的,实现了容器数据持久化功能
具名和匿名挂载
匿名挂载
-v 容器内路径
# 匿名挂载
docker run -d -p 8080:8080 --name nginx01 -v /ect/nginx nginx
# 查看所有的卷volume的情况
[root@iZwz909zuxxmim3sok3i3qZ ~]# docker volume ls
# 这里发现,这种就是匿名挂载,在-v只写了容器内的路径,没有写容器外的路径
DRIVER VOLUME NAME
local 237dd6794961c2f83236fda3b1d5720587c5ac5b999898d7929282ebc05278b3
local c79e077e18d9022b3b1f5cf2b4aa55a20b35200f0e8dd23e7e7a30630ff9c5c8
# 具名挂载 -v 卷名:容器内路径
[root@iZwz909zuxxmim3sok3i3qZ home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
377afbabf7e1f60e24558f6719497bddb187f8d922eff59f35e7f758892f63f9
[root@iZwz909zuxxmim3sok3i3qZ home]# docker volume ls
DRIVER VOLUME NAME
local 237dd6794961c2f83236fda3b1d5720587c5ac5b999898d7929282ebc05278b3
local c79e077e18d9022b3b1f5cf2b4aa55a20b35200f0e8dd23e7e7a30630ff9c5c8
local juming-nginx
# 查看卷的位置
[root@iZwz909zuxxmim3sok3i3qZ home]# docker volume inspect juming-nginx
[
{
"CreatedAt": "2023-12-03T16:52:49+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
所有的docker容器内的卷,没有指定目录的情况下都在/var/lib/docker/volumes/xxxx/_data
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用具名挂载
如何确认是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
扩展
# 通过 -v 容器内路径:ro, rw 改变读写权限
# -ro readonly # 只读
# -rw readwrite # 可写
# 一旦设置了容器权限 容器对我们挂载出来的内容就有限定
[root@iZwz909zuxxmim3sok3i3qZ home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
[root@iZwz909zuxxmim3sok3i3qZ home]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# ro 说明这个路径只能通过宿主机来操作,容器内部无法操作
初识Dockerfile
Dockerfile就是用来构建docker镜像的构建文件!命令脚本!
通过这个脚本可以生成镜像,镜像一层一层的,脚本一个个的命令,每个命令都是一层
# 创建一个Dockerfile文件,名字随意 建议Dockerfile
# 文件中的内容 指令(大写) 参数
FORM centos
VOLUME ["volume01", "volume02"] # 生成镜像的时候就挂载
CMD echo "------end-----"
CMD /bin/bash
# 这里的每个命令就是一层
# 创建镜像
# build命令 -f 镜像的文件名路径 -t 镜像名字 最后要加.
docker build -f dockerfile1 -t queqian/centos:1.0 .
# 启动一下创建的镜像
[root@iZwz909zuxxmim3sok3i3qZ docker-test-volume]# docker run -it queqian/centos /bin/bash
[root@4fb75d639cd4 /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
# 这里看到了 volume01 volume02 这里的目录就是我们生成镜像的时候 自动挂载的
这时候是匿名挂载。可以用docker inspect 容器id查看容器信息,里面Mounts有挂载信息,表明挂载到宿主机的哪个位置。
这种方式使用的频率比较高,因为我们通常会构建自己的镜像。
假设构建镜像时没有挂载卷,要手动镜像挂载 -v
数据卷容器
多个mysql同步数据!
# 使用创建的镜像创建docker01容器
[root@iZwz909zuxxmim3sok3i3qZ _data]# docker run -it --name docker01 queqian/centos
[root@810162154bdd /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
# 使用创建的镜像创建docker02容器 并且使用--volumes-from 来继承docker01的挂载卷
[root@iZwz909zuxxmim3sok3i3qZ _data]# docker run -it --name docker02 --volumes-from docker01 queqian/centos
# 这时候docker02的挂载卷应该跟docker01的同步数据
# 测试
# 在docker01容器内volume1创建一个文件
[root@810162154bdd volume01]# touch dockerContainer01.txt
# 到docker02容器内的volume1查看文件 会发现有这个dockerContainer01.txt
这里docker02 相当于继承docker01 。 docker01 相当于数据卷容器。只要通过--volumes-from 就能实现容器间的数据共享
要继承的子容器 --volumes-from 继承的父容器
如果此时删除docker01容器,其他容器的数据并不会消失,但是如果把宿主机里面挂载的数据卷文件夹给删除,所有容器的数据都会消失。这就意味着所有的容器都跟宿主机上的数据卷文件挂钩