前言
数据卷基础
Docker联合文件系统
Docker镜像
是有多层只读文件
叠加而成,当运行起一个容器的时候,Docker会在制只读层上创建一个读写层
。如果运行中的容器需要修改文件,那么并不会修改只读层的文件,只会把该文件复制到读写层
然后进行修改,只读层的文件就被隐藏了。当删除了该容器之后,或者重启容器之后,之前对文件的更改会丢失,镜像的只读层以及容器运行是的“读写层”被称为联合文件系统(Union File System)
为了实现容器与主机之间、容器与容器之间共享文件
,容器中数据的持久化
,将容器中的数据备份
、迁移
、恢复
等,Docker加入了数据卷(volumes)机制。简单的讲,就是做了一个文件夹的实时共享,有点像局域网的文件共享。
数据卷的特点
数据卷存在于宿主机的文件系统中,独立于容器,和容器的生命周期是分离的。
数据卷可以是目录也可以是文件,容器可以利用数据卷与宿主机进行数据共享,实现了容器间的数据共享和交换。
容器启动初始化时,如果容器使用的镜像包含了数据,这些数据会拷贝到数据卷中。
容器对数据卷的修改是实时进行的。
数据卷的变化不会影响镜像的更新。数据卷是独立于联合文件系统,镜像是基于联合文件系统。镜像与数据卷之间不会相互影响。
主要是用于有状态容器。
为什么需要数据卷呢?
Data volumes
Container 运行过程中产生的临时数据写入镜像的读写层,随容器的删除而删除,需要保留的公有数据可以写在卷上。
Volume types
容器中使用Volumes
Docker管理-自动生成的Volume
1 | docker run --name b2 -it -v /data busybox |
Mounts中的json数组:卷名称Name,卷在宿主机目录Source,卷在容器中目录 Destination,使用的本地驱动。
在宿主机上该文件夹下写一个文件,容器内也能实时感知。
1 | # 宿主机 |
在容器中写的文件,在宿主机目录下也能实时感知
1 | # 在容器内追加文件内容 |
bind-mount-volume 绑定挂在卷
如果宿主机上该路径不存在,run的时候指明宿主机路径,会自动创建。
1 | # source 宿主机/data/volumes/b2 路径下 |
1 | cd /data/volumes/b2 |
1 | # 退出后,容器被删除,但数据卷还在 |
只要数据卷不删除,下次再启动时,容器内换一个路径也会映射到宿主机的数据卷中。
1 | docker run --name b2 -it --rm -v /data/volumes/b2:/data/web/html busybox |
过滤 docker inspect显示的消息
1 | # 简单的Go语言魔板过滤 |
可不可以让两个容器关联到一个宿主机的卷上,让容器间共享数据呢?
1 | # b3容器也关联宿主机上b2关联的目录,只是在容器中是 /data目录 |
b3容器的目录在/data 目录下, b2容器的目录在/data/web/html/ 目录下,但二者都挂载到 宿主机的 /data/volumes.b2 目录下。二者可以通过宿主机共享数据。
每次在容器初始化时,都要手动指定挂载的宿主机卷,如果不想记住宿主机卷的存放目录呢?
Docker 支持去复制别人的的存储卷目录。假设启动b2时,容器内卷与宿主机卷已经定义好了,启动b3时,要使用和b2一模一样的存储卷目录。
因此,可以定义一个容器,什么也不做,只要指定它宿主机与容器Volumes的对应规则即可,其他容器启动时复制当前容器的规则。
这个容器就可以被当做底层基础支撑容器,其它容器启动时基于该容器获得环境的设定。如果仅仅是这样,有点大材小用,之前介绍或 Joined-Containers:共享网络 UTS/NETWORK/IPC。
如果两个容器关系紧密,如NT:Nginx+Tomcat,Nginx对外提供服务,Tomcat向Nginx提供服务。二者可以使用相同的基础容器,共享网络。Tomcat监听LO接口,Nginx监听对外接口,外部访问Nginx,由Nginx反代到Tomcat,Tomcat想等于被隐藏起来。
除此之外,Tomcat提供动服务,Nginx提供静态服务,二者要想共享数据,在基础容器里可以实现共享目录。
1 | # 创建一个底层基础支撑容器,一般不要随意删除 |
这种依赖于人的记忆的容器间的关系,不利于管理与维护,可以用DockerFIle 来指定基础容器的属性,容器间的依赖、启动顺序等等。这就是容器编排-Docker Compose。只能实现单机容器编排。