容器数据卷
什么是容器数据卷#
docker 的理念回顾
将应用和环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化
例如 MySQL:容器删了,数据丢失!需求:MySQL 数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
这就是卷技术!目录挂在,将我们容器内的目录,挂载到Linux上!
总结一句话:容器的持久化和同步操作!容器间也是可以数据共享的
使用数据卷#
方式一:直接使用命令挂载 -v
$ docker run -it --name="容器名" -v 主机内目录:容器内目录 -p 主机端口:容器内端口 镜像名
# 将容器中的/home目录挂载到宿主机的~/File/centos_test目录下,内部和外部的文件都会互相自动同步
$ docker run -it -v ~/File/centos_test:/home centos /bin/bash
查看一下容器的信息
$ docker inspect 容器id
测试文件同步步骤和效果
再次进行测试
1. 停止容器
2. 宿主机上修改文件
3. 启动容器
4. 容器内的数据依旧是同步的
好处:我们之后修改只需要在本地修改即可,容器内会自动同步。
实战测试:安装 MySQL#
问题:MySQL 的持久化问题!
# 获取镜像
$ docker pull mysql
# 运行容器,需要做数据挂载!安装启动mysql需要配置密码的,这是要注意的点!
# 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动镜像
docker run -p 3306:3306 --name=mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql
# 启动成功后,进入容器内部拷贝配置文件,到宿主主机。
docker cp mysql:/etc/mysql ~/File/docker_mysql
# 删除mysql容器,重新创建容器
docker stop mysql
docker rm mysql
# 启动
# -d 后台运行
# -p 端口映射
# -v 卷挂载
# -e 环境配置
# --name 容器名
# --privileged=true 授权执行
# -i: 以交互模式运行容器
# MYSQL_ROOT_PASSWORD:数据库密码(自己设置)
$ docker run -i -d -p 3310:3306 -v ~/File/docker_mysql/mysql-file:/var/lib/mysql-file -v ~/File/docker_mysql/conf:/etc/mysql -v ~/File/docker_mysql/data:/var/lib/mysql -v ~/File/docker_mysql/logs:/var/log/mysql -v /etc/localtime:/etc/localtime -e MYSQL_ROOT_PASSWORD=123456 -privileged=true --name=mysql01 mysql
docker exec -it 容器名或者ID /bin/bash
mysql -hlocalhost -uroot -p123456
select host,user,plugin,authentication_string from mysql.user;
ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password BY '新密码';
flush privileges;
命令解释
-p 端口映射
--privileged=true 挂载文件权限设置
--restart unless-stopped 设置 开机后自动重启容器
-v ~/File/docker_mysql/mysql:/etc/mysql 挂载配置文件
-v ~/File/docker_mysql/logs:/logs \ 挂载日志
-v ~/File/docker_mysql/data:/var/lib/mysql \ 挂载数据文件 持久化到主机,
-v /etc/localtime:/etc/localtime 容器时间与宿主机同步
-e MYSQL_ROOT_PASSWORD=123456 设置密码
-d mysql:8 后台启动,mysql
启动成之后外部使用 navicate 测试,navicate 连接到服务器的 3310,服务器的 3310 和容器的 3306 映射,这个时候我们就可以连接上了!
在本地创建一个数据库
这是测试一下,将 MySQL 的容器删除,发现挂载到本地的数据卷在本地还保存着。
mysql 数据备份#
虽然我们可以通过数据卷的操作,将数据挂载到宿主机中,但是我们在实际的项目开发中会有这样的问题,当有新的服务器或者部署新的版本的 mysql 时,需要同步当前的数据库中的所有数据时,就显得力不从心,这时就需要进行 mysql 的数据备份。
# 导出全部数据
docker exec 容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /data/all--databases.sql
# 导出指定数据库数据
docker exec 容器id sh -c 'exec mysqldump --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /data/all--databases.sql
# 导出指定数据库数据不包含数据
docker exec 容器id sh -c 'exec mysqldump --no-data --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /data/all--databases.sql
# 执行 sql 文件到 mysql 中
docker exec -i mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /root/xxx.sql
具名挂载和匿名挂载#
- 匿名挂载
# -v 容器内路径
$ docker run -d -p --name nginx -v /etc/nginx nginx
# 查看所有卷的情况
$ docker volume ls
DRIVER VOLUME NAME
local a7ea06ddbf53d1e879f304470b4775abdf9e455d2fba0a589588a6f50ba22137
# 这里发现,这种就是匿名挂载,我们在-v的时候,只写了容器内的路径,没有写容器外的路径!
- 具名挂载
# 通过 -v 卷名:容器内路径
$ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
$ docker volume ls
$ docker volume inspect 卷名
所有 docker 容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
但是发现一个问题,mac 中是没有这个目录的,可以通过 screen Library/Containers/com.docker.docker/Data/vms/0/tty
(路径后半部分可能会变) 进入到 LinuxKit 虚拟机内部,通过其他 linux 命令看到里边就是一个定制的 linux 系统,运行了 dockerd, containerd 等后台进程。注意可使用 Ctrl
+A
+D
快捷键退出 screen 窗口。
关于 screen
的更多具体命令可以看我关于 screen
的 Blog。
进入之后可以看到实际的文件是保存在 LinuxKit 虚拟机内部,g.docker 在 mac os 或者 windows 上,都是基于特定的虚拟化技术运行 linux 虚拟机,并不共享宿主机内核。
我们通过具名挂载可以方便的找到我们的一个卷,大多数情况下使用具名挂载
# 如何确定是具名挂载还是匿名挂载还是指定路径挂载
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载
- 拓展
在后面加上 ro
或者是 rw
,改变读写权限
# 一旦这个设置了容器权限,容器对我们挂载出来的内容就限定了!
$ docker run -d -P --name nginx02 -v jumping-nginx:/etc/nignx:ro nginx
$ docker run -d -P --name nginx02 -v jumping-nginx:/etc/nignx:rw nginx
# 通过-v 容器内路径:ro rw 改变读写权限
# ro readonly 只读 只能通过宿主机操作,容器内无法改变
# rw readwrite 可读可写
初识 Dockerfile#
Dockerfile 就是用来构建 docker 镜像的构建文件!命令脚本。
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是一个一个的命令,每个命令都是一层。
创建一个 dockerfile
文件中的内容,指令(大写)参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash
# 这里的每个命令就是镜像的一层
$ docker build -f ~/File/docker_test_volume/dockerfile1 -t hudu/centos:1.0 .
启动自己的镜像测试
这个卷一定和外部有一个同步的目录!
1. 通过命令查看容器的具体信息
2. 看到挂载的卷在外部的具体的目录
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 容器内路径
数据卷容器#
两个 MySQL 同步数据
启动 3 个容器,通过我们刚才自己的写镜像启动Ctrl
+P
+Q
, 不关闭容器退出
$ docker run -it --name docker01 hudu/centos:1.0 /bin/bash
$ docker run -it --name docker02 --volumes-from docker01 hudu/centos:1.0
$ docker run -it --name docker03 --volumes-from docker01 hudu/centos:1.0
测试:删除 docker01,查看一下,docker02 和 docker03 都还有这个文件。
通过 docker inspect 容器id
可以发现,其实他们都是映射到了宿主机的相同的目录下。
多个 MySQL 实现数据共享
$ run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name=mysql01 mysql
$ run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name=mysql02 --volumes-from mysql01 mysql
实现两个容器数据共享同步
结论,容器之间可以配置信息传递,数据卷容器的生命周期一直持续到没有容器使用为止。
但是一旦持久化到了本地,本地的数据是不会删除的。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: