Docker初学者入门详细学习(3)

220 阅读9分钟

本章主要学习容器数据卷的知识,通过绑定容器卷,到达主机跟容器内数据共通的目的。同时添加了mysql的实战练习,巩固操作。容器卷挂载方式、挂载查看、数据卷容器等知识。

容器数据卷

什么是容器数据卷

docker的理念回顾

将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失! 需求:数据可以持久化

MySQL,容器删了,删库跑路! 需求:MySQL数据可以存储在本地!

容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!

这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上!

image.png
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的

使用数据卷

方式一: 直接使用命令来挂载 -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文件下都没有任何文件

image.png
测试同步

# 这时候在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 端口 以及刚刚的密码 测试链接。会得到下图

image.png

# 查看本机的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上创建一个数据库

image.png

# 再次查看本机的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容器,其他容器的数据并不会消失,但是如果把宿主机里面挂载的数据卷文件夹给删除,所有容器的数据都会消失。这就意味着所有的容器都跟宿主机上的数据卷文件挂钩