docker 数据卷和网络
概述
本文介绍 Docker 中与数据持久化相关的 volume 和与通信相关的 network。
volume (数据卷)
默认情况下,容器一旦被移除,其中包含的数据也会自动消失。为避免这种情况,需要用到数据持久化技术。
Docker 提供宿主机与容器之间共享文件,从而将数据持久化于宿主机。其具体分为两种方式 —— volumes 和 bind mounts。另外,对于 Linux 而言,Docker 提供 tmpfs mount ,它将数据直接保存于宿主机内存之中,而非容器之中。
volumes
volumes 由 Docker 创建并管理,且其中数据仅能由 Docker 进程操纵,其位于由 Docker 所管理的宿主机文件系统部分 (对于 Linux 而言,具体位于 /var/lib/docker/volumes/)。
Docker 提供 docker volume 命令管理 volumes,该命令的详细信息具体如下:
1 | Usage: docker volume COMMAND |
为持久化容器数据,我们可在启动容器时使用 -v 或 --mount 参数将特定 volumes 挂载于容器的特定目录。举例如下:
1 | // 挂载volumeName数据卷至centos的/var/lib目录,且指定数据卷为只读模式。 |
-v与--mount的区别在于:前者混杂多种使用情况,后者使用键值对形式将这些情况区分开来。建议使用--mount挂载数据卷。
有关 volumns 的使用,作如下几点说明:
volumes具体细分为Named volumes和Anonymous volumes,前者由用户分配数据卷名称,后者由 Docker 分配数据卷名称。命令docker run -v volumeName:/var/lib:ro centos使用的是Named volumes,命令docker run -v /var/lib:ro centos使用的是Anonymous volumes。- 如果容器目录不存在,则自动创建;如果数据卷不存在,则自动创建。
- 如果将空数据卷挂载至容器非空目录,则容器目录内容会首先被自动复制至数据卷,然后该容器挂载并使用数据卷。
- 启动容器时,可使用
--volumes-from参数以挂载特定容器中的数据卷,从而实现两容器数据卷内容共享。
bind mounts
bind mounts 由用户创建并管理,其中数据可为任何进程操纵,其所在位置由用户自主决定。
为持久化容器数据,我们可在启动容器时使用 -v 或 --mount 参数将宿主机指定目录与容器特定目录绑定挂载。举例如下:
1 | // 绑定挂载宿主机/usr/lib目录与centos的/var/lib目录,且指定为只读模式。 |
有关 bind mounts 的使用,作如下几点说明:
- 如果容器目录或文件不存在,则自动创建;如果宿主机目录或文件不存在,此时分为两种情况:若使用
-v参数,则总是创建相应的目录,若使用--mount参数,则不会创建相应目录或文件,并提示报错。 - 对于
bind mounts而言,其不存在 “容器目录内容自动复制至数据卷” 的类似情况,而是容器直接挂载并使用宿主机目录或文件。
有关绑定传播 (bind propagation) 的知识官方文档讲的很模糊,自己没有看懂。另外,官网文档中言及 “Bind propagation is an advanced topic and many users never need to configure it.”,所以可以省略这部分内容。
tmpfs mounts
如果容器运行所产生的数据为无关数据,处理此数据的一种绝佳方法是使用 tmpfs mounts,如此操作后,这些数据便位于宿主机内存之中,从而减小容器大小。当容器停止运行后,这些数据会自动消失。
tmpfs mounts仅限于 Linux 使用。
tmpfs mounts无法挂载于多个容器,而volumes和bind mounts可以。
为使用 tmpfs mounts,我们可在启动容器时使用 --tmpfs 或 --mount 参数挂载容器特定目录至宿主机内存。举例如下:
1 | // 挂载centos的/var/lib目录至宿主机内存 |
--tmpfs与--mount的区别在于:前者不允许配置tmpfs相关选项 (具体指代tmpfs-size和tmpfs-mode),且不能被用于swarm service。
network (网络)
容器间相互通信,依赖于 Docker 强大的网络功能。
Docker 网络架构由三部分组成:Container Network Model (CNM)、Libnetwork、驱动程序,其中 CNM 为网络设计标准,它规定了 Docker 网络架构的基本组成要素;Libnetwork 为 CNM 的具体实现;驱动程序提供不同的网络拓扑实现。
CNM
CNM 规定了三个基本组成要素:沙盒 (Sandbox)、终端 (Endpoint)、网络 (Network),其中沙盒是一个独立的网络栈,包括以太网接口、端口、路由表、DNS配置等内容;终端指代虚拟网络接口,负责将沙盒连接至网络;网络为 802.1d 网桥的软件实现。三者连接关系如图所示:
驱动程序
Docker 内置若干驱动程序,包括 bridge、overlay、host、macvlan、none,我们在此一一介绍。
bridge
bridge network 仅适用于单机 (single docker daemon host) 使用,借助于链路层软件设备——网桥,实现在所负责网段之内转发流量。
Docker 内置一个默认 bridge network。容器启动时,如果未使用
--network参数指定网络,则其存在于默认 bridge network。当然,用户也可自定义 bridge network。自定义 bridge network 与默认 bridge network 的区别:
- 前者提供容器之间的 DNS 解析,而后者不提供。在默认 bridge network 之中,容器间通信只能基于 IP 地址 (一种取巧方式是使用
--link,随后使用容器名通信。其实际是在容器的 hosts 文件下添加一条 IP 地址与容器名的映射,因此其本质仍是基于 IP 地址进行通信)。而在自定义 bridge network 之中,容器间可基于 IP 地址、容器名、网络别名实施通信。 - 前者可以提供更好的隔离性能。未使用
--network指定网络的容器均归于默认 bridge network,这使得其中包含各种应用,鱼龙混杂,无法提供较好的隔离。 - 对于前者而言,容器可随时连接或断开连接;对于后者而言,如果希望断开连接,需要停止容器并以合适的网络选项重新启动它。
- 对于后者而言,基于
--link参数启动的容器与 link 对象容器共享相同的环境变量。
- 前者提供容器之间的 DNS 解析,而后者不提供。在默认 bridge network 之中,容器间通信只能基于 IP 地址 (一种取巧方式是使用
overlay
overlay network 适用于多机 (multiple docker daemon host) 间构建分布式网络,借助于 VXLAN 隧道技术,实现分布式网络内转发流量。
当初始化 swarm 或添加 Docker host 至现有 swarm 时,两个网络被自动创建:ingress,一个默认 overlay network;docker_gwbridge,一个桥接网络,允许容器访问外网。
host
如果某个容器使用 host network,则其与宿主机共享相同的网络栈 (例如,IP 地址、端口)。
macvlan
….
none
如果不希望容器使用网络功能,则可指定
--network参数为none。
这里涉及太多的网络知识,不懂。