docker 数据
现在我们有数据层(镜像层和容器可写层)和 volume 都可以用来存放数据,具体使用的时候要怎样选择呢?考虑下面几个场景:
- Database 软件 vs Database 数据
- Web 应用 vs 应用产生的日志
- 数据分析软件 vs input/output 数据
- Apache Server vs 静态 HTML 文件
相信大家会做出这样的选择:
- 前者放在数据层中。因为这部分内容是无状态的,应该作为镜像的一部分。
- 后者放在 Data Volume 中。这是需要持久化的数据,并且应该与镜像分开存放。
默认情况下,在容器内创建的所有文件都存储在可写容器层中,数据不能容易的被迁移到其他地方。当该容器不再存在时,数据也不会持久存在,并且如果另一个进程需要数据,则可能很难从容器中获取数据。因此,对于一些需要持久化的docker数据,需要在主机中存储文件。
解释:当该容器不再存在时,数据也不会持久存在
- 当容器被删除后,通过镜像创建并启动一个新的容器后,之前容器中发生的所有改变全部都会消失。
- 容器内运行期间产生的数据在容器关闭后,又回到你启动容器时的原始镜像状态。
如何解决不消失?要么创建一个新镜像,要么挂载到宿主机,接下来本章就讲解下挂载。
docker 数据持久化
Docker提供了三种不同的方式用于将宿主的数据挂载到容器中:volumes,bind mounts,tmpfs volumes。
volumes是Docker数据持久化机制。bind mounts依赖主机目录结构,volumes完全由Docker管理。
无论选择哪种挂载方式,数据在容器中看起来都是一样的。宿主机的数据在容器的文件系统中总被显示为目录或文件。如何简单的理解这三种挂载方式的不同之处呢,我们可以理解为在这三种方式下,容器内的数据在宿主机中存放的位置不同
- Volumes方式下:容器内的数据被存放到宿主机(linux)一个特定的目录下(/var/lib/docker/volumes/)。这个目录只有Docker可以管理,其他进程不能修改。如果想持久保存容器的应用数据,Volumes是Docker推荐的挂载方式。
Bind mounts方式下:容器内的数据被存放到宿主机文件系统的任意位置,甚至存放到一些重要的系统目录或文件中。Docker或daocker之外的进程也可以任意对他们进行修改;
bind mounts允许建立docker容器中的文件与本地文件之间的映射关系,容器中的进程写入这个文件的内容会保存到映射的本地文件中,与volume不同的是,bind mounts不由docker同一管理,volume存放在docker的特定区域,而bind mounts可以位于主机的任意位置,由于bind mounts不由docker管理,也就无法像volume一样使用docker命令去管理查看相应的信息,依据主机文件系统的不同,bind mounts也具有不同的性能,bind mounts可以挂载到文件,也可以挂载到本地目录。- tmpfs方式下:容器的数据只会存放到宿主机的内存中,不会被写到宿主机的文件系统中,因此不能持久保存容器的应用数据。
与volumes相比,Bind mounts绑定装载具有有限的功能。当使用bind mounts时,宿主机的目录或文件被挂载到容器中。容器将按照挂载目录或文件的绝对路径来使用或修改宿主机的中的数据。
小区,粪池,各家房子下水道连接粪池…
Volume的适用场景
- 多个容器间需要共享数据。如果volume卷 没有手动被创建,它将会在首次挂载到某个容器之前被自动创建,当容器被停止或删除时,这个volume不会随之被删除。多个容器可以同时以rw或ro的方式挂载这个volume。只有手动指定删除volume,它才会被删除。
- 当宿主机并没有专用于Docker的文件系统结构时。使用volume可以使宿主机的配置与容器的运行解耦。
- 当你希望将数据保存到远程主机或云上。
- 当你希望在不同的宿主机直接备份/恢复/迁移数据时,volume是一个很好的选择。你可以停止运行使用volume的容器,然后直接备份volume所在的目录即可,如
/var/lib/docker/volumes/
bind mounts的适用场景
- 将宿主机的系统配置文件共享给容器,这是Docker为容器提供DNS配置的默认方式,即通过bind mounts的方式将宿主的的/etc/resolv.conf文件挂载到容器中。
- 将宿主机开发环境中的源代码或实验结果共享给容器。例如:你在宿主机上进行一个项目Maven的测试,每次你在宿主机上对Maven项目进行了更改后,容器就可以直接获取更改后的结果.
- 当你可以确定宿主机的文件系统结构应该与容器内部完全一致时。
如果使用绑定挂载或卷,注意:
- 如果将一个空的卷挂载到容器中的一个包含文件或目录的目录,这些文件或目录会被复制到卷中。类似的,如果启动容器时指定一个不存在的卷,则自动创建一个空的卷。这是预先填充其他容器需要的数据的好方法。
- 如果将绑定挂载或非空卷挂载到容器中的一个包含文件或目录的目录,则这些文件或目录会被挂载遮盖,就像先将文件保存到 Linux 主机上的 /mnt 中,然后将一个 USB 驱动器挂载到 /mnt 中一样。在卸载 USB 驱动器之前,/mnt 中的内容将被 USB 驱动器的内容遮盖。遮盖的文件不会被删除或更改,但在装入绑定挂载或卷时不可访问。