》一文中介绍了 docker 数据卷(volume) 的基本用法。随着使用的深入,笔者对 docker 数据卷的理解与认识也在不断的增强。本文将在前文的基础上介绍 docker 数据卷的原理及一些高级用法。如果您想先了解 docker 数据卷的基本概念与用法,请先移步。
文件系统说起。出于效率等一系列原因,docker 容器的文件系统在宿主机上存在的方式很复杂,这会带来下面几个问题:
- 文件。
- 删除时,容器中产生的数据将丢失。
解决这些问题,docker 引入了数据卷(volume) 机制。数据卷是存在于一个或多个容器中的特定文件或文件夹,这个文件或文件夹以独立于 docker 文件系统的形式存在于宿主机中。数据卷的最大特定是:其生存周期独立于容器的生存周期。
- 文件时,使用数据卷可以规避这种限制带来的问题。
create 创建数据卷inspect 显示数据卷的详细信息 ls 列出所有的数据卷prune 删除所有未使用的 volumes,并且有 -f 选项rm 删除一个或多个未使用的 volumes,并且有 -f 选项名称为 hello 的数据卷并通过 ls 命令进行查看:
删除数据卷,后面笔者会介绍一些实际使用中与数据卷的删除有关的一些实践。
type 指定挂载方式,我们这里用到的是 volume,其实还可以有 bind 和 tmpfs。volume-driver 指定挂载数据卷的驱动程序,默认值是 local。source 指定挂载的源,对于一个命名的数据卷,这里应该指定这个数据卷的名称。在使用时可以写 source,也可以简写为 src。destination 指定挂载的数据在容器中的路径。在使用时可以写 destination,也可以简写为 dst 或 target。readonly 指定挂载的数据为只读。volume-opt 可以指定多次,用来提高更多的 mount 相关的配置。
名称为 hello 的数据卷,然后把它挂在到容器中的 /world 目录。通过 inspect 命令查看容器的详情中的 "Mounts" 信息可以验证实际的数据卷挂载结果 :
插件的,我们可以通过下面的命令进行安装:
登录用户名、密码和数据存放目录:
文件都存储在远程主机的 /home/nick/sshvolume 目录中。进入容器 testcon 然后在 /world 目录中创建一个文件,然后打开远程主机的 /home/nick/sshvolume 目录进行查看,你新建的文件是不是已经出现在那里了!
文件系统中找了个文件管理数据卷相关的数据。因此你可能根本不需要知道数据卷文件在宿主机上的存储位置(事实上抱着刨根问底的精神我们还是很想搞清楚它背后的工作原理!)。
名称的目录)挂载到容器中指定的目录上。这里使用的挂载方式为绑定挂载(bind mount),所以挂载完成后的宿主机目录和容器内的目标目录表现一致。
代码:
包括 rootfs,init-layer 里的内容,/proc 设备等),docker 只需要通过 chdir 和 pivot_root 切换进程的根目录到 rootfs 中,这样容器内部进程就只能看见以 rootfs 为根的文件系统以及被 mount 到 rootfs 之下的各项目录了。例如我们启动的 testcon 中的文件系统为:
- 文件会被复制到数据卷中。
- 显示数据卷中的数据。如果原来容器中的目录中有数据,那么这些原始数据会被隐藏掉。
内容。掌握第二个规则可以保证挂载数据卷后的数据总是你期望的结果。
添加数据卷
添加数据卷:
生成镜像并且以该镜像启动容器时会挂载一个数据卷到 /data 目录。根据我们已知的数据覆盖规则,如果镜像中存在 /data 目录,这个目录中的内容将全部被复制到宿主机中对应的目录中,并且根据容器中的文件设置合适的权限和所有者。VOLUME 指令不能挂载主机中指定的目录。这是为了保证 Dockerfile 的可一致性,因为不能保证所有的宿主机都有对应的目录。在 Dockerfile 中使用 VOLUME 指令之后的代码,如果尝试对这个数据卷进行修改,这些修改都不会生效!下面是一个这样的例子:
用户 nick,并且能够看到 /data 目录挂载的数据卷。但是 /data 目录内并没有文件 test.txt,更别说 test.txt 文件的所有者属性了。要解释这个现象需要我们了解通过 Dockerfile 创建镜像的过程:生成的临时镜像运行一个容器,执行一条指令并执行类似 docker commit 的命令得到一个新的镜像。这条类似 docker commit 的命令不会对挂载的数据卷进行保存。
解决 Dockerfile 中数据卷的初始化问题:
文件以及它们的权限和所有者设置会被复制到数据卷中。方法可以解决 Dockerfile 中数据卷的初始化问题。就是利用 CMD 指令和 ENTRYPOINT 指令的执行特点:与 RUN 指令在镜像构建过程中执行不同,CMD 指令和 ENTRYPOINT 指令是在容器启动时执行。因此使用下面的 Dockerfile 也可以达到对数据卷的初始化目的:
解决了用户数据的持久化问题,能够让用户在容器中产生的数据超出容器自身的生命周期。因此对于容器技术来说掌握数据卷的使用非常必要。希望本文能够帮助您理解数据卷相关的内容。