容器的数据卷
什么是容器的数据卷
docker的理念回顾
将应用和环境打包成一个镜像
对于数据,如果数据都在容器中,那么我们删除容器,数据就会丢失,这样会存在很大的问题
需求:容器内的数据需要持久化
例如MySQL如果数据都存在容器中,那么容器删了,数据就丢失了,所以需要MySQL的数据可以存储在本地
容器和宿主机之间有一种数据共享的技术,docker容器中产生的数据,可以同步到本地宿主机存储
这就是卷技术
将我们容器内的目录,挂载到宿主机Linux上
总结: 容器可以持久化数据和同步数据操作,容器之间的数据也是可以共享的
容器的数据卷三种挂载方式
1 指定路径挂载
# 指定路径挂载
# 命令
# docker run -it -v /主机目录:容器目录
# 测试
# 删除所有容器(生产环境慎用)
[root@alnk home]# docker rm -f $(docker ps -aq)
# 删除所有镜像(生产环境慎用)
[root@alnk home]# docker rmi -f `docker images -qa`
# 启动一个容器并且挂载一个目录
[root@alnk home]# docker run -it -v /home/ceshi:/home centos /bin/bash
# 查看
[root@alnk home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48acac4be5e7 centos "/bin/bash" About a minute ago Up About a minute crazy_liskov
[root@alnk home]# docker inspect 48acac4be5e7
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi", # 宿主机内目录
"Destination": "/home", # docker容器内的地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
测试文件同步
# 1 在容器内创建/home/docker.txt,在宿主机/home/ceshi目录可以查看到docker.txt文件
# 容器内
[root@48acac4be5e7 home]# pwd
/home
[root@48acac4be5e7 home]# ls
[root@48acac4be5e7 home]# touch docker.txt
# 宿主机内
[root@alnk home]# cd ceshi/
[root@alnk ceshi]# pwd
/home/ceshi
[root@alnk ceshi]# ls
docker.txt
# 2 停止容器,然后在宿主机/home/ceshi目录创建base.txt,最后启动容器,然后查看容器/home目录下是否有base.txt
# 2.1 停止容器
[root@alnk ceshi]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48acac4be5e7 centos "/bin/bash" 10 minutes ago Up 10 minutes crazy_liskov
[root@alnk ceshi]# docker stop 48acac4be5e7
48acac4be5e7
# 2.2 创建base.txt文件
[root@alnk ceshi]# touch base.txt
# 2.3 启动容器
[root@alnk ceshi]# docker start 48acac4be5e7
48acac4be5e7
# 2.4 进入容器查看,存在base.txt文件
[root@alnk ceshi]# docker exec -it 48acac4be5e7 /bin/bash
[root@48acac4be5e7 /]# ls /home/
base.txt docker.txt
总结: 以后可以在本地修改文件内容,容器也会自动同步文件
2 匿名挂载
# 匿名挂载
# -v 容器内路径
# -P(大写P) 随机映射端口
[root@alnk mysql]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@alnk mysql]# docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume情况
# 这里发现,这种就是匿名挂载,我们在 -v 后只写了容器的路径,没有写容器外宿主机的路径
[root@alnk mysql]# docker volume ls
DRIVER VOLUME NAME
local 23b1b49331e52db9ef2c90369b5ef7a10a59c7648e5d823c344ce99967ffa092
3 具名挂载
# 具名挂载
# -v 卷名:容器内路径
[root@alnk mysql]# docker run -d -P --name nginx02 -v jumingguazai-nginx:/etc/nginx nginx
5db0a8143afe57bce8e5fd0adc5a28fb1ebc9748cb78bb567ca93b59d9e0506f
# 查看所有的卷情况
[root@alnk mysql]# docker volume ls
DRIVER VOLUME NAME
local jumingguazai-nginx
# 查看具体某个卷的详细情况
[root@alnk mysql]# docker volume inspect jumingguazai-nginx
[
{
"CreatedAt": "2021-08-24T10:57:12+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/jumingguazai-nginx/_data",
"Name": "jumingguazai-nginx",
"Options": null,
"Scope": "local"
}
]
小结
docker容器内的所有卷,在没有指定目录的情况下,那么都是挂载在宿主机/var/lib/docker/volumes目录下
我们可以通过具名挂载很方便的找到一个卷,大多数情况下我们使用具名挂载
拓展
# 通过 -v 卷名:容器内路径:ro/rw 改变读写权限
# ro 只读权限
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内是无法操作的
[root@alnk ~]# docker run -d -P --name nginx05 -v juming-ro:/etc/nginx:ro nginx
[root@alnk ~]# docker exec -it nginx05 /bin/bash
root@9ed43b3cebf8:/# cd /etc/nginx/
root@9ed43b3cebf8:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
root@9ed43b3cebf8:/etc/nginx# touch test.txt # 容器内创建文件报错
touch: cannot touch ‘test.txt‘: Read-only file system
# rw 读写权限
[root@alnk ~]# docker run -d -P --name nginx06 -v juming-rw:/etc/nginx:rw nginx
[root@alnk ~]# docker exec -it nginx06 /bin/bash
root@e855897172c4:/# cd /etc/nginx/
root@e855897172c4:/etc/nginx# touch test.txt
root@e855897172c4:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params test.txt uwsgi_params
root@e855897172c4:/etc/nginx#
练习
# 安装MySQL,并且数据要持久化
# 1 获取镜像
# https://hub.docker.com/_/mysql 可以去官网查看具体版本
[root@alnk ceshi]# docker pull mysql:5.7
5.7: Pulling from library/mysql
e1acddbe380c: Pull complete
......
Digest: sha256:7cf2e7d7ff876f93c8601406a5aa17484e6623875e64e7acc71432ad8e0a3d7e
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
[root@alnk ceshi]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 6c20ffa54f86 6 days ago 448MB
# 2 运行容器,需要做数据挂载,安装启动mysql需要配置密码,具体可以参考官网
# docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 启动mysql容器
[root@alnk ~]# 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
# 参数解释
# -d 后台运行
# -p 端口映射
# -v 挂载卷
# -e 环境配置
# --name 容器名字
# 3 测试,在宿主机连接MySQL容器
# 3.1 宿主机没有启动mysql数据库
[root@alnk ~]# ps -ef|grep mysql
polkitd 28393 28370 0 10:35 ? 00:00:00 mysqld
root 29289 27971 0 10:39 pts/3 00:00:00 grep --color=auto mysql
# 3.2 宿主机启动了MySQL容器
[root@alnk ~]# docker ps
05d6248b5f65
# 3.3 查看宿主机IP
[root@alnk ~]# ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
inet 172.17.0.3/20 brd 172.17.15.255 scope global eth0
# 3.4 连接MySQL容器
[root@alnk ~]# mysql -h172.17.0.3 -uroot -p123456
MySQL [(none)]>
# 3.5 查看宿主机的挂载目录
# conf 和 data 目录已经挂载到MySQL容器中
[root@alnk mysql]# pwd
/home/mysql
[root@alnk mysql]# ls
conf data
# 删除MySQL容器查看conf和data目录依然存在
# 说明挂载到本地的数据卷即使容器删除,数据也没有丢失,实现了容器数据的持久化
[root@alnk mysql]# docker rm -f 05d6248b5f65
05d6248b5f65
[root@alnk mysql]# ls
conf data
容器的数据卷总结
# 容器的数据卷 使用的三种方法
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:容器内路径 # 指定路径挂载。docker volume ls 查看不到这种挂载
数据卷容器
初识dockerfile
dockerfile 就是用来构建docker镜像的构建文件,是一个命令脚本,后面的章节会详细讲解,这里先大致了解一下
通过这个脚本可以生成镜像,镜像是一层一层的,脚本是从上到下按顺序执行的,每个命令都是镜像的一层
# 通过dockfile创建镜像# 创建一个dockerfile文件,文件名字建议为Dockerfile# 文件中的内容,指令需要大写# 这里的每个指令就是镜像的一层FROM centosVOLUME ["volume01", "volume02"]CMD echo "---end---"CMD /bin/bash# 1 编辑dockerfile[root@alnk diy_centos]# cat dockerfile1FROM centosVOLUME ["volume01", "volume02"]CMD echo "---end---"CMD /bin/bash# 2 通过dockerfile创建自己的镜像# docker build -f [dockfile] -t [名称:tag]# 注意这里的名称必须是小写,不然会报错[root@alnk diy_centos]# docker build -f ./dockerfile1 -t alnk/centos:1.0 ./........Successfully built 054fab57047cSuccessfully tagged alnk/centos:1.0# 3 查看镜像[root@alnk diy_centos]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEalnk/centos 1.0 054fab57047c 13 seconds ago 209MB
# 通过dockfile创建的镜像启动容器# 1 启动容器# volume01 volume02 目录就是我们生成镜像的时候自动挂载的目录[root@alnk diy_centos]# docker run -it --name diy_centos_01 alnk/centos:1.0[root@d73f4179c91f /]# ls... volume01 volume02# 2 在宿主机查看自动挂载的卷的路径[root@alnk diy_centos]# docker inspect d73f4179c91f"Mounts": [ { "Type": "volume", "Name": "46c3221cd9c47e29cdd41b8c19c7620eae4323ac6843b30ed0c7c75480450271", "Source": "/var/lib/docker/volumes/46c3221cd9c47e29cdd41b8c19c7620eae4323ac6843b30ed0c7c75480450271/_data", "Destination": "volume01", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }, { "Type": "volume", "Name": "f43218b4b1f7e6805fa70dbac5b67b9224228e490a6f94bf78ce3516b53eb568", "Source": "/var/lib/docker/volumes/f43218b4b1f7e6805fa70dbac5b67b9224228e490a6f94bf78ce3516b53eb568/_data", "Destination": "volume02", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" }],# 这种方式使用的十分多,因为我们通常会构建自己的镜像# 假设构建镜像的时候没有挂载卷,那么就需要手动挂载了[-v 卷名:容器内路径]
数据卷容器
# 数据卷容器 --volumes-from# 1 启动三个容器,通过之前自定义的镜像[root@alnk diy_centos]# docker run -it --name test01 alnk/centos:1.0[root@05e5fd9bd70d /]# ls... volume01 volume02[root@05e5fd9bd70d /]# cd volume01/[root@05e5fd9bd70d volume01]# ls[root@05e5fd9bd70d volume01]# touch test01.txt[root@05e5fd9bd70d volume01]# lstest01.txt# --volumes-from[root@alnk diy_centos]# docker run -it --name test02 --volumes-from test01 alnk/centos:1.0[root@1925106464b9 /]# ls # test01容器创建的内容同步到test02容器... volume01 volume02[root@1925106464b9 /]# cd volume01/[root@1925106464b9 volume01]# lstest01.txt# --volumes-from[root@alnk diy_centos]# docker run -it --name test03 --volumes-from test01 alnk/centos:1.0[root@948e43f85e01 /]# ls volume01/test01.txt# 删除test01,查看test02和test03是否可以访问test01.txt文件# 依旧可以访问# 可以看出 test01 test02 test03 之间应该是互相拷贝的关系[root@alnk diy_centos]# docker rm -f test01test01[root@alnk diy_centos]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES948e43f85e01 alnk/centos:1.0 "/bin/sh -c /bin/bash" About a minute ago Up About a minute test031925106464b9 alnk/centos:1.0 "/bin/sh -c /bin/bash" 3 minutes ago Up 3 minutes test02[root@alnk diy_centos]# docker exec -it test02 /bin/bash[root@1925106464b9 /]# ls volume01/test01.txt
多个mysql实现数据共享
# 这个时候可以实现数据同步# 1 启动第一个mysql[root@alnk diy_centos]# 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# 2 启动第二个mysql # --volumes-from[root@alnk diy_centos]# docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7# 3 进入到第一个MySQL容器创建一个alnk数据库[root@alnk diy_centos]# mysql -h172.17.0.3 -p3306 -uroot -p123456MySQL [(none)]> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys |+--------------------+MySQL [(none)]> create database alnk;MySQL [(none)]> show databases;+--------------------+| Database |+--------------------+| information_schema || alnk || mysql || performance_schema || sys |+--------------------+# 4 进入第二个mysql容器查看是否存在alnk数据库# 存在alnk数据库[root@alnk diy_centos]# mysql -h172.17.0.3 -p3307 -uroot -p123456MySQL [(none)]> show databases;+--------------------+| Database |+--------------------+| information_schema || alnk || mysql || performance_schema || sys |+--------------------+
容器之间的数据信息可以共享
数据卷容器的生命周期一直持续到没有共享的数据卷容器为止
但是一旦你持久化到了本地,那么即是没有容器了,本地的数据也是不会删除的