什么是数据卷 数据不应该放在容器中,如果容器删除,数据就会丢失!==需求:数据 持久化==
MYSQL,容器删了=删库跑路!==需求:MYSQL数据可以存储在本地==
==> 需要容器之间有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!说白了就是目录的挂载,将容器内的目录,挂载到 Linux 上
总结:容器的持久化和同步操作! 容器间也可以数据共享!
使用数据卷
方式一:直接使用命令来挂载 -V
1 2 3 4 5 6 7 8 9 10 11 12 13 docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口 # 测试 xxx@data:~$ sudo docker run -it -v /home/dutir/xxx/ceshi:/home centos /bin/bash # 查看容器id xxx@data:~$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 43b6593461e7 centos "/bin/bash" 2 minutes ago Up 2 minutes quizzical_varahamihira # 查看容器详细信息 xxx@data:~$ sudo docker inspect 43b6593461e7 # 看到挂载
、
测试文件的同步
再来测试
1 2 3 4 5 6 7 # 1.停止容器 # 2.宿主机上修改文件 # 3.启动容器 # 4.容器内的数据依旧是同步的
好处:我们以后修改只需要在本地修改即可,容器内会自动同步!
实战:安装MySQL 思考:MySQL 的数据持久化问题,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 获取镜像 docker pull mysql:5.7 # 运行容器,需要做数据挂载! # 官方测试 $ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag # -e 配置环境,这里要配置密码 # 启动我们的 -d 后台运行 -p 端口映射 -v 数据卷挂载,可挂载多个 -e 环境配置 --name 容器名字 xxx@data:~$ sudo docker run -d -p 3310:3306 -v /home/dutir/xxx/mysql_test/conf:/etc/mysql/conf.d -v /home/dutir/xxx/mysql_test/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 # 启动成功之后,我们在本地使用 sqlyog 连接测试 # sqlyog 连接到本地的3310,本地3310侦听服务器宿主机的3310,宿主机的3310和容器内的3306映射,这个时候就可以连接上了 # 在本地sqlyog测试创建一个数据库,查看一下我们映射的路径是否ok! # test_for_docker以后,docker里多出这个数据库
即使把容器删除
发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器持久化功能!
具名和匿名挂载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # 匿名挂载(不指定主机名) -v 容器内路径 docker run -d -P --name nginx01 -v /etc/nginx nginx # 查看所有本地volume(数据卷) 乱码的都是匿名卷 xxx@data:~$ sudo docker volume ls DRIVER VOLUME NAME local 51ed233d17e5c740a92f70e075335dd59cbcf913dd03390d64880893a6a6b043 local mysql_lawbda_my-db # 这里发现,这种就是匿名挂在,我们在 -v 时只写了容器内的路径,没有写容器外的路径! # 具名挂载 docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx nginx xxx@data:~$ sudo docker volume ls DRIVER VOLUME NAME local 51ed233d17e5c740a92f70e075335dd59cbcf913dd03390d64880893a6a6b043 local juming-nginx local mysql_lawbda_my-db # 通过 -v 卷名:容器内路径 # 查看一下这个卷(这里查看mysql_lawbda_my-db) xxx@data:~$ sudo docker volume inspect mysql_lawbda_my-db [ { "CreatedAt": "2022-04-04T17:14:49+08:00", "Driver": "local", "Labels": { "com.docker.compose.project": "mysql_lawbda", "com.docker.compose.version": "1.27.4", "com.docker.compose.volume": "my-db" }, "Mountpoint": "/var/lib/docker/volumes/mysql_lawbda_my-db/_data", "Name": "mysql_lawbda_my-db", "Options": null, "Scope": "local"
所有达到docker容器内的卷,没有指定目录的情况下都是在/val/lib/docker/volumes/xxxx/_data
我们通过具名挂载 可以方便找到我们的一个卷,大多数情况在使用具名挂载
1 2 3 4 5 # 如何确定是具名挂载还是匿名挂在,还是指定路径挂载! -v 容器内路径 # 匿名挂载 -v 卷名:容器内路径 # 具名挂载 -v /宿主机路径:容器内路径 # 指定路径挂载
拓展:
1 2 3 4 5 6 7 8 9 10 # 通过 -v 容器内路径:ro rw 改变读写权限 ro read only # 只读 rw readwrite # 可读可写 # 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了! docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:ro nginx docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:rw nginx # ro 只要看到ro,就说明这个路径只能通过宿主机来改变,容器内部是无法操作的
初识Dockerfile
方式二:生成镜像的时候就挂载出来
Dockerfile 就是用来构建 docker 镜像的构建文件! 就是一段命令脚本!先体验一下!
通过这个脚本可以生成镜像,镜像是一层一层的,脚本就是一个一个的命令,每个命令就是一层。
1 2 3 4 5 6 7 8 9 10 11 12 13 # 创建一个dockerfile文件,名字可以随机, 建议 Dockerfile # 文件中的内容 指令(都是大写) 参数 FROM centos VOLUME ["volume01","volume02"] CMD echo "----end----" CMD /bin/bash # 这里的每个命令,就是镜像的一层!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # docker build 构建镜像 root@data:/home/dutir/xxx/docker-test-volume# docker build -f /home/dutir/xxx/docker-test-volume/dockerfile1 -t wjm/centos:1.0 . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos ---> 5d0da3dc9764 Step 2/4 : VOLUME ["volume01","volume02"] ---> Running in eedc2cf7a5b3 Removing intermediate container eedc2cf7a5b3 ---> 80396b388983 Step 3/4 : CMD echo "----end----" ---> Running in 734dc31604b0 Removing intermediate container 734dc31604b0 ---> 5ef9da00ac40 Step 4/4 : CMD /bin/bash ---> Running in 593084c92533 Removing intermediate container 593084c92533 ---> 8edda645979e Successfully built 8edda645979e Successfully tagged wjm/centos:1.0 root@data:/home/dutir/xxx/docker-test-volume# # 启动一下自己生成的镜像 root@data:/home/dutir/xxx/docker-test-volume# docker images REPOSITORY TAG IMAGE ID CREATED SIZE wjm/centos 1.0 8edda645979e 4 minutes ago 231MB root@data:/home/dutir/xxx/docker-test-volume# docker run -it 8edda645979e /bin/bash
这个目录就是我们生成镜像时自动挂载的,数据卷目录。
这个和外部一定有一个同步的目录!dockerfile里只指定了容器内目录,一定是匿名挂载,所以容器外、宿主机上肯定有乱码的挂载。
1 2 # docker inspect 查看容器信息 # 找到 Mounts,查看卷挂载的路径,符合匿名挂载的默认路径/var/lib/docker/volumes/xxx/
在容器里的 volume01 下新建一个 container.txt 文件。
1 2 3 4 5 6 7 8 9 [root@4b4b467cf777 /]# ls bin etc lib lost+found mnt proc run srv tmp var volume02 dev home lib64 media opt root sbin sys usr volume01 [root@4b4b467cf777 /]# cd volume01 [root@4b4b467cf777 volume01]# ls [root@4b4b467cf777 volume01]# touch container.txt [root@4b4b467cf777 volume01]# ls container.txt [root@4b4b467cf777 volume01]#
测试一下刚才的文件是否同步出去。
1 2 3 4 5 6 7 8 9 # 复制 Mounts 下的路径 /var/lib/docker/volumes/951ce898d681397c29606b61bb9da1102d7594f4d0cd069c4b63fbd96b171f96/_data # cd 到这里 root@data:~# cd /var/lib/docker/volumes/951ce898d681397c29606b61bb9da1102d7594f4d0cd069c4b63fbd96b171f96/_data root@data:/var/lib/docker/volumes/951ce898d681397c29606b61bb9da1102d7594f4d0cd069c4b63fbd96b171f96/_data# ls container.txt # 发现新建的 container.txt 文件 root@data:/var/lib/docker/volumes/951ce898d681397c29606b61bb9da1102d7594f4d0cd069c4b63fbd96b171f96/_data#
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像时没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径
数据卷容器
即容器和容器间同步
多个 Mysql 数据如何同步?
==所有 docker 之间共享的卷都是独立的,每个docker有自己的数据卷。新建时拷贝父容器的备份。所以只要有一份存在,数据都不会丢失。==
1 2 3 # 启动3个容器,通过我们刚才自己写的镜像启动 # 首先启动 docker01
1 2 3 # 启动 docker02,volume 从 docker01 继承 # docker01 就叫做数据卷容器
在 docker01 修改数据, docker02 会同步吗?测试一下。
回到 docker02 查看
docker01 创建的内容同步到 docker02 了
再从 docker01 继承,启动 docker03,新建 docker03.txt
在 docker03 里创建的文件,在 docker01 和 docker02 里都同步了。
只要是通过 —volume-from ,我们就可以实现容器间的数据共享。
把 docker01 整个 rm 掉,docker02 和 docker03 的文件都还在。
1 2 3 4 5 6 7 8 9 # 测试:可以删除docker01,查看一下docker02和docker03是否还可以访问这个文件 # 依旧可以访问 # 测试:查看宿主机的volume,还是存在 root@data:~# cd /var/lib/docker/volumes/2bdf8b38df84ffea344d0f758e7be2c2045c54f270a9da362b12246a1d78d636/_data root@data:/var/lib/docker/volumes/2bdf8b38df84ffea344d0f758e7be2c2045c54f270a9da362b12246a1d78d636/_data# ls docker01.txt docker03.txt
==所有 docker 之间共享的卷都是独立的,每个docker有自己的数据卷。新建时 拷贝 父容器的备份。所以只要有一份存在,数据都不会丢失。==
回到问题:多个 Mysql 数据如何同步?
1 2 3 4 5 6 7 # -v 容器内路径,匿名挂载 xxx@data:~$ sudo docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7 # 用 --volumes-from 可以实现两个容器同步 xxx@data:~$ sudo docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 --volumes-from mysql01 mysql:5.7
结论 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止(所有容器都停止)。
但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的。所以重要的文件存在宿主机上就好啦。
参考 以上是看 b 站教学视频记的笔记。
教程地址:【狂神说Java】Docker最新超详细版教程通俗易懂_哔哩哔哩_bilibili