数据卷介绍
Docker可以将开发的应用和运行的环境一起打包形成容器运行,Docker容器产生的数据,如果不通过Commit生成一个新的镜像,使得这些数据成为镜像的一部分保存下来,那当容器删除时,数据自然也就没有了(相当于别人删除跑路),为了能够保存数据在Docker中我们使用数据卷。
卷是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但不属于联合文件系统。因此绕过联合文件系统提供一些用于持续存储或共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生命周期,因此Docker不会在容器删除时删除挂载的数据卷。
数据卷的特点:
- 数据卷可在容器之间共享或重用数据
- 数据卷的更改会直接生效
- 数据卷的更改不会包含到镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
简单使用数据卷
运行容器时,指定挂载数据卷命令:
docker run -it -v 主机目录: 容器目录
现将主机目录/home/test和容器的/home建立数据卷,首先在容器创建test.java文件,再去主机目录下查看是否有该文件。
实现如下图
查看容器元数据,数据卷挂载信息,可以通过以下命令
docker inspect 容器id
可以从Mounts节点中查看到我们设置的数据卷信息。
即使容器停止运行或者删除,仍然可以实现数据同步,本地的数据卷不会丢失。
Mysql容器中实现数据卷
Linux的MySQL默认的数据文档存储目录为/var/lib/mysql,默认的配置文件的位置/etc/mysql/conf.d,为确保MySQL镜像或容器删除后,不会造成数据丢失,因此建立数据卷来保存MySQL的数据和文件。
核心命令
docker run -d -p 6603: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
实现
[root@iZbp1896jyjbijmf4j9oi7Z test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 bb4a9178d7f0 3 days ago 684MB
nginx latest 605c77e624dd 6 months ago 141MB
tomcat latest fb5657adc892 6 months ago 680MB
hello-world latest feb5d9fea6a5 9 months ago 13.3kB
centos latest 5d0da3dc9764 10 months ago 231MB
portainer/portainer latest 580c0e4e98b0 16 months ago 79.1MB
[root@iZbp1896jyjbijmf4j9oi7Z test]# docker run -d -p 6603: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
Unable to find image 'mysql:5.7' locally
5.7: Pulling from library/mysql
72a69066d2fe: Already exists
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Already exists
37f2405cae96: Already exists
e2482e017e53: Already exists
70deed891d42: Already exists
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
02af66b77e97331f552948afec44240282ff26c49eb6f3d530a43a75e086c282
[root@iZbp1896jyjbijmf4j9oi7Z test]# cd ~
[root@iZbp1896jyjbijmf4j9oi7Z ~]# cd /home
[root@iZbp1896jyjbijmf4j9oi7Z home]# ls
mysql test test.java www
[root@iZbp1896jyjbijmf4j9oi7Z home]# cd mysql/conf
[root@iZbp1896jyjbijmf4j9oi7Z conf]# ls
[root@iZbp1896jyjbijmf4j9oi7Z conf]# cd /home/mysql/data
[root@iZbp1896jyjbijmf4j9oi7Z data]# ls
auto.cnf client-cert.pem ibdata1 ibtmp1 private_key.pem server-key.pem
ca-key.pem client-key.pem ib_logfile0 mysql public_key.pem sys
ca.pem ib_buffer_pool ib_logfile1 performance_schema server-cert.pem
[root@iZbp1896jyjbijmf4j9oi7Z data]#
如果使用配置的密码连接mysql服务失败,原因很大可能是本机挂载的配置文件已有文件,将容器中的配置给覆盖掉,我们将相应的本机文件中的文件配置删除即可。
数据卷常用命令
- 创建本地数据卷
docker volume create my -vol
2.查看所有数据卷
docker volume ls
3.查看指定数据卷的信息
docker volume inspect my-vol
4.删除数据卷
docker volume rm my-vol
5.删除容器之相关的卷
docker rm -v ...
数据卷是被设计用持久化数据的,它的生命周期独立容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在向垃圾回收这样的机制帮助我们去处理没有引用的数据卷,如果需要在删除时同时移除数据卷。可以在删除容器时使用docker rm -v这个命令。
无主的数据卷会占用空间,清理可用以下命令
docker volume prune
5.使用 --mount创建数据卷,挂载一个主机目录作为数据卷。使用–mount标记可以指定挂载一个本地主机的目录到容器中去。
核心命令
docker run -d -P \
--name web \
-- mout type =bind ,source =/src /webapp ,target = /opt /webapp \
training /webapp
上面的命令将主机的/src/webapp目录挂载到容器的/opt/webapp目录。 用户可以放置一些程序到本地目录,来查看容器是否正常工作,本地目录的路径必须是绝对路径,如果目录不存在Docker会自动创建。
Docker挂载主机目录的默认权限为读写,用户也可以通过添加readnoly参数指定为只读。
$ docker run -d -P \
--name web \
# -v /src/webapp:/opt/webapp:ro \
--mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
training/webapp \
python app.py
加了readonly之后,就挂载为只读了。如果你在容器内/src/webapp目录新建文件,会显示如下错误
/src/webapp # touch new.txt
touch: new.txt: Read-only file system
具名挂载和匿名挂载
匿名挂载
匿名挂载就是在指定数据卷的时候,不指定容器路径对应的主机路径,这样对应映射的主机路径就是默认的路径/var/lib/docker/volumes/中自动生成一个随机命名的文件夹。
匿名挂载一个Nginx容器:
docker run -d -P --name nginx01 -v /etc/nginx nginx
查看所有的数据卷volume的情况,VOLUMN NAME这里的值是真正存在的目录。
docker volume ls
具名挂载
具名挂载,就是指定文件夹名称,区别于指定路径挂载,这里的指定文件夹名称是在Docker指定的默认数据卷路径下的。通过docker volume ls 命令可以查看当前数据卷的目录情况。
# 具名挂载文件
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 查看所有数据卷
docker volume ls
# 查看指定数据卷命令
docker volume inspect 数据卷名称
匿名挂载和具名挂载,指定路径挂载的命令区别如下:
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
数据卷映射的相关参数:
ro —— readonly 只读。设置了只读则只能操作宿主机的路径,不能操作容器中的对应路径。
rw ----- readwrite 可读可写
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:参数 nginx
Dockerfile设置数据卷
构建步骤:
1.编写一个dockerfile文件
2.docker build构建成为一个镜像
3.docker run 运行镜像
4.docker push 发布镜像(DockerHub ,阿里云镜像仓库!)
我们可以在Dockerfile中使用VOLUME指令给镜像添加一个或多个数据卷
下面使用Dockerfile构建一个新的镜像,docker file01文件的内容,匿名挂载了volume01和volume02两个目录:
在主机上创建以下文件
编写文件
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
执行构建镜像
docker build -f /home/docker-test-volume /dockerfile01 -t ethan/centos:1.0 .
![在这里插入图片描述](https://img-blog.csdnimg.cn/323bbbcfe3c14914825bb5d53f765b02.png)
完成镜像的生成后,启动自己的生成的容器。
docker run -it 镜像id /bin/bash
可以看到自动挂载的数据卷目录,下面查看对应宿主机的数据卷目录
docker inspect 容器id
可以看到Mounts下有宿主机的挂载目录。因为dockerfile中没有指定宿主机目录,所以属于匿名挂载,在/var/lib/docker/volumes/目录下生成了随机命名的路径。
容器数据卷
容器数据卷是指建立数据卷,来同步多个容器间的数据,实现容器间的数据同步。
#1.启动容器1,volume01、volume02为挂载目录。
docker run -it --name cnetos01 ethan/centos:1.0
#2.启动容器2,通过参数--volumes-from,设置容器2和容器1建立数据卷挂载关系。
docker run -it --name centos02 --volumes-from cnetos01 ethan/centos:1.0
#3.在容器2中的volume01中添加test.java文件
cd volume0
touch test.java
#t退出查看可以看到容器1的文件也会添加上了
同步两个MySQL的数据库和配置文件,与上面的操作相同,首先建立数据卷,然后给另一个MySQL容器建立容器数据卷挂载。
docker run -d -p 6603: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
docker run -d -p 6604:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7