自动化:docker卷介绍
站内链接:
Intro
原因
- docker 中的
image
都是Readonly
- docker 中的
数据存储层
在运行时创建, 此时状态为:Read-and-write
- docker 中的
数据存储层
会跟随container
的生命周期终止而销毁, 注意容器停止并不代表容器生命周期就已经结束
但是数据存储层因为文件系统隔离会有如下的问题:
- 随着容器的消亡(dead)而销毁
- 容器中数据不能在不同主机之间进行数据迁移
- 数据写入
数据存储层
需要内核提供 UFS, 会有额外的性能损耗 - 数据不能在多个容器中进行共享
为了解决如上的问题, docker 提供了类似外接数据盘
的方式来进行数据持久化
, 数据迁移
等概念. 另外, 在讲解下面的内容之前我们先简单的介绍一下容器的生命周期:
其中 Deleted 代表着 Dead, Stoped 代表着 Exited, 只有容器被删除才代表着一个容器的生命周期结束, 此时容器中相关的文件系统资源才会被释放.
卷创建方式
docker 提供 3 中不同的方式将数据盘挂载到 docker 中
- volume: 使用 docker 默认的文件中存储数据卷,
/var/lib/docker/volumes/
- bind mount: 将主机上的任何文件或者目录(绝对路径)挂载到容器中
- tmpfs: 将外接数据存储到内存中, 参考 redis, 不会写入文件系统中
上述三者分别指向不同的区域, 一个为内存, 一个为文件系统, 一个为 docker area, 见
Macos
mac 上的 docker 历史版本:
- boot2docker: 自带一个最小化的 VirtualBox 的 Linux 镜像, 在虚拟机中运行 docker daemon.
- Doocker Toolbox: boot2docker 的继任者, 原理一致, 但是封装了很多工具, 增加可用性
- Docker for Mac: 内嵌虚拟机, 使用 XHYVE 虚拟机, 并做了很多定制化
正因为 mac 或者 windows 系统中对 docker 外层进行的包装, 所以在使用卷的时候跟 ubuntu 系统有很大的不同, 下面以 mongodb 为例简单介绍下因为虚拟机导致的一些在 linux 系统上碰不到的问题:
1 | # 1. ubuntu上启动mongodb, 将数据目录bind到宿主机, mac上也是同样方式启动mongodb |
但是, 如果使用数据卷挂载容器内的数据目录, 在 ubuntu 系统上通过docker inspect mongovolume
可以直接在宿主机上找到输出的 mount 目录, 但是在 mac 系统上需要通过额外的操作:
1 | # 1. 方式1(不推荐, 有乱码) |
最后, 这里再提及一些 mac 的 docker 虚拟机产生的另外一个问题, 那就是 IO 非常非常慢, 我在 mac 跑一个 flask 应用服务, 然后连接 docker 中的 mysql 服务, 页面每次刷新都需要好久, 此时需要使用docker-sync
来辅助实现 IO 的同步操作, 具体原因和操作间参考链接中的说明.
volume
Intro
volume
是 docker 中数据持久化的最佳方式(除了 Mac 之外), 数据卷
是可以供一个或者多个容器使用的特殊目录, 它绕过 UFS, 提供了很多特性:
- 在容器中共享和重用, 可以安全的在容器之间共享
- 类似文件系统, 在 volume 中的改动会立刻生效
- 根据容器存储层概念, 对数据卷的更新, 不会影响镜像
- 根据持久化概念, 数据卷默认会一直存在, 即使容器被删除
- 内置
docker volume
来进行数据卷的管理 - volume 在生成时, 默认会随机生成一个名称
- 相比 bind volume, volume 更容易备份和迁移
参数
-v/--volume
:格式由三个字段组成,卷名:容器路径:选项列表
--mount
: 由多个键值对组成, 由,
进行分隔, 格式为key=value
其中 mount 中的键值对可以为如下的值:
- type: bind, volume, tmpfs
- source: 如果忽略, 则为匿名卷, 否则为卷名
- destination/dst/target: 文件或者目录会被挂载到的容器中的 path
- volume-opt: 操作变量
另外 MAC 上查看 volume 的路径值的方式见 1.3 节的介绍.
Example
创建一个卷: docker volume create unusebamboo
获取卷列表: docker volume ls
查看某一个数据卷的详细信息: docker volume inspect unusebamboo
删除数据卷: docker volume rm unusebamboo
挂载卷:
1 | # --mount |
默认情况下, volume 创建的 Driver 为local
, 此时任何容器不能共享此数据卷数据.
容器共享
多个容器之间可以共享一个数据卷, 通过--volumes-from
实现父子容器的数据卷共享操作
1 | # 1. 启动一个父容器, 设置共享目录 |
bind
Intro
使用bind mount
方式, 可以将当前宿主机上的任何文件/目录挂载到容器中, 注意, 它同 volume 有如下的区别:
- 挂载的文件和目录可以被任何进程更改, 注意这里同 volume 的区别
- 如果文件或者目录不存在, 自动创建
- 该方式不能使用
docker volume
进行管理
bind mount 的使用场景如下:
- 宿主机共享配置到容器中, 例如
/etc/resolv.conf
用于 DNS 解析 - 宿主机与容器共享代码或构建工具, 这是大部分的需求
- 宿主机和容器的文件和目录结构需要保持一致时
参数
-v/--volume
:主机文件目录:容器文件目录:选项列表
--mount
: 格式为key=value
其中选项列表可以为: ro, consistent, delegated, cached, z, Z. 其中键值对的类型:
- type: bind, volume, tmpfs
- source: 主机路径
- destination/dst/target: 容器路径
- readonly: 存在时更改 Propagation
- consistently: 在 MAC 中生效, 可以为 consistent, delegated, cached
Example
启动 container, 并绑定共享磁盘, 此时不会提前创建 volume
1 | # --mount |
tmpfs
Intro
使用tmpfs
, 存储在内存中的临时文件系统, 一般在注重安全, 不需要持久化的情况下使用.
限制: tmpfs 挂载不能再容器之间共享, 仅能在 Linux 下生效
参数
挂载tmpfs
时, 可以使用--mount
来增加两个配置项
- tmpfs-size: 默认无限制, 表示 tmpfs 的最大大小
- tmpfs-mode: 8 进制文件模式
Example
1 | # --mount |
Inspect
配置
1 | # 获取配置 |
挂载与网络
1 | # 获取某一个容器的 ip |
清理
1 | # 删除所有container: |