Docker 的优点很是明显,尤为是对于开发者来讲,它提供了一种全新的软件发布机制。也就是说使用 docker 镜像做为软件产品的载体,使用 docker 容器提供独立的软件运行上下文环境,使用 docker hub 等提供镜像的集中管理,这其中最重要的是使用 Dockerfile 定义容器的内部行为和关键属性来支持软件运行。可是实际的生产环境每每须要定义数量庞大的 docker 容器,而且容器之间具备错综复杂的联系。手动的记录和配置这些复杂的容器关系,不只效率低下并且容易出错。因此,咱们迫切须要一种像 Dockerfile 定义 docker 容器同样可以定义容器集群的编排和部署工具。因而,Docker Compose 出现了(其实应该说 Fig 出现了,docker 收购了 Fig 并更名为 compose)。
Dockerfile 重现一个容器,compose 则用来重现容器的集群。
说明:本文的演示环境为 ubuntu 16.04。html
编排(orchestration)
编排指根据被部署的对象之间的耦合关系,以及被部署对象对环境的依赖,制定部署流程中各个动做的执行顺序,部署过程所须要的依赖文件和被部署文件的存储位置和获取方式,以及如何验证部署成功。这些信息都会在编排工具中以指定的格式(好比配置文件或特定的代码)来要求运维人员定义并保存起来,从而保证这个流程可以随时在全新的环境中可靠有序地重现出来。redis
部署(deployment)
部署是指按照编排所指定的内容和流程,在目标机器上执行环境初始化,存放指定的依赖文件,运行指定的部署动做,最终按照编排中的规则来确认部署成功。docker
因此说,编排是一个指挥家,他的大脑里存储了整个乐曲此起彼伏的演奏流程,对于每个小节每一段音乐的演奏方式都了然于胸。而部署就是整个乐队,他们严格按照指挥家的意图用乐器来完成曲谱的执行。最终,二者经过协做就能把每一位演奏者独立的演奏经过组合、重叠、衔接来造成高品位的交响乐。这也是 docker compose 要完成的使命。ubuntu
笔者在前文《Docker Compose 简介》中演示了官方的示例,本文再也不赘述,接下来咱们去探索 compose 的工做原理。先来了解两个 compose 中经常说起的概念:数据结构
project
经过 docker compose 管理的一个项目被抽象称为一个 project,它是由一组关联的应用容器组成的一个完整的业务单元。简单点说就是一个 docker-compose.yml 文件定义一个 project。
咱们能够在执行 docker-compose 命令时经过 -p 选项指定 project 的名称,若是不指定,则默认是 docker-compose.yml 文件所在的目录名称。运维
service
运行一个应用的容器,实际上能够是一个或多个运行相同镜像的容器。能够经过 docker-compose up 命令的 --scale 选项指定某个 service 运行的容器个数,好比:工具
$ docker-compose up -d --scale redis=2
了解了上面的基本概念以后,让咱们一块儿看看 compose 的一次调用流程:spa
右上角的 docker-compose 定义了一组 service 来组成一个 project,经过 docker-compose.yml 中 service 的定义与 container 创建关系(service 与容器的对应关系),最后使用 container 来完成对 docker-py(Python 版的 docker client) 的调用,向 docker daemon 发起 http 请求。注意,这里的 project, service 和 container 对应的都是 docker-compose 实现中的数据结构。下面让咱们结合上图来介绍 docker-compose 工做的大体流程。命令行
首先,用户执行的 docker-compose up 命令调用了命令行中的启动方法,功能很是简单。一个 docker-compose.yml 文件定义了一个 project,docker-compose up 提供的命令行参数则做为这个 project 的启动参数交由 project 模块处理。3d
而后,若是当前宿主机已经存在与该应用对应的容器,docker-compose 则进行行为逻辑判断。若是用户指定能够从新启动已有服务,docker-compose 就会执行 service 模块的容器重启方法,不然就直接启动已有容器。这两种操做的区别在于前者会中止旧的容器,建立并启动新的容器,并把旧容器移除掉。在这个过程当中建立容器的各项自定义参数都是从 docker-compose up 命令和 docker-compose.yml 中传入的。
接下来,启动容器的方法也很简洁,这个方法中完成了一个 docker 容器启动所需的主要参数的封装,并在 container 模块执行启动。
最后,contaier 模块会调用 docker-py 客户端来执行向 docker daemon 发起建立容器的 POST 请求。
因而可知 docker-compose 工做的总体流程很是清晰、简洁!
前面咱们提到当前宿主机已经存在与该应用对应的容器,docker-compose 会进行判断并决定是否从新启动已有服务。下面咱们就经过 demo 来演示几个常见的场景(咱们依然使用前文中提到的官方 demo)。
强制 recreate
Recreate 就是删除现有的容器而且从新建立新的容器,为 docker-compose up 命令指定 --force-recreate 选项能够强制 recreate 容器:
建立个别容器
若是应用中的个别 service 对应的容器被删除了,docker-compose up 命令会新建相关的容器:
启动个别容器
与上面相似,若是应用中的个别 service 对应的容器被中止(stop)了,docker-compose up 命令会从新启动相关的容器:
Docker-compose 整体上给人的感受是并不复杂。本文只是从概览的角度梳理了一遍 docker-compose 的总体执行流程,主要目的是理解它的工做原理。至于相关的使用技巧等细节,笔者会在接下来的文章中进行介绍。
参考:
《Docker 容器和容器云》