1. 简介

  • docker-compose 能帮我们做什么?

    • 在实际的生产环境往往需要定义数量庞大的 docker 容器,并且容器之间具有错综复杂的联系。
    • 手动的记录和配置这些复杂的容器关系,不仅效率低下而且容易出错。
    • 所以,我们迫切需要一种像 Dockerfile 定义 docker 容器一样能够定义容器集群的编排和部署工具。于是,Docker Compose 出现了
  • 什么是编排和部署?

    • 编排(orchestration):
      • 编排指根据被部署的对象之间的耦合关系,以及被部署对象对环境的依赖,制定部署流程中各个动作的执行顺序,部署过程所需要的依赖文件和被部署文件的存储位置和获取方式,以及如何验证部署成功。这些信息都会在编排工具中以指定的格式(比如配置文件或特定的代码)来要求运维人员定义并保存起来,从而保证这个流程能够随时在全新的环境中可靠有序地重现出来。
    • 部署(deployment):
      • 部署是指按照编排所指定的内容和流程,在目标机器上执行环境初始化,存放指定的依赖文件,运行指定的部署动作,最终按照编排中的规则来确认部署成功。
  • Dockerfile 重现一个容器,compose 则用来重现容器的集群。

  • Compose 是 Docker 提供的一个命令行工具,用来定义和运行由多个容器组成的应用,负责实现对 Docker 容器集群的快速编排。

  • 使用 compose,我们可以通过 YAML 文件声明式的定义应用程序的各个服务,并由单个命令完成应用的创建和启动。

  • 使用 Compose 大致有3个步骤:

    • 使用 Dockerfile 定义应用程序环境,以便在任何地方重现该环境
    • 在 docker-compose.yml 文件中定义组成应用程序的服务,以便各个服务在一个隔离的环境中一起运行
    • 运行 docker-compose up 命令,启动并运行整个应用程序
  • 其实 compose 提供的命令可以管理应用的整个生命周期:

    • Start, stop, rebuild services
    • 查看运行中 service 的状态
    • 输出运行中 service 的日志
    • 在 service 中执行一次性的命令
  • Docker Compose Quick Start

    2. 原理

    Docker Compose 将所管理的容器分为三层,分别是工程(project)、服务(service)、容器(container)

  • project:

    • 通过 docker compose 管理的一个项目被抽象称为一个 project,它是由一组关联的应用容器组成的一个完整的业务单元。简单点说就是一个 docker-compose.yml 文件定义一个 project
    • 我们可以在执行 docker-compose 命令时通过 -p 选项指定 project 的名称,如果不指定,则默认是 docker-compose.yml 文件所在的目录名称。
  • service:
    • 运行一个应用的容器,实际上可以是一个或多个运行相同镜像的容器。可以通过 docker-compose up 命令的 —scale 选项指定某个 service 运行的容器个数,比如:
      1. $ docker-compose up -d --scale redis=2

了解了上面的基本概念之后,让我们一起看看 compose 的一次调用流程:


Docker Compose - 图1

  • 首先,用户执行的 docker-compose up 命令调用了命令行中的启动方法,功能非常简单。一个 docker-compose.yml 文件定义了一个 project,docker-compose up 提供的命令行参数则作为这个 project 的启动参数交由 project 模块处理。

  • 然后,如果当前宿主机已经存在与该应用对应的容器,docker-compose 则进行行为逻辑判断。如果用户指定可以重新启动已有服务,docker-compose 就会执行 service 模块的容器重启方法,否则就直接启动已有容器。这两种操作的区别在于前者会停止旧的容器,创建并启动新的容器,并把旧容器移除掉。在这个过程中创建容器的各项自定义参数都是从 docker-compose up 命令和 docker-compose.yml 中传入的。

  • 接下来,启动容器的方法也很简洁,这个方法中完成了一个 docker 容器启动所需的主要参数的封装,并在 container 模块执行启动。
  • 最后,contaier 模块会调用 docker-py 客户端来执行向 docker daemon 发起创建容器的 POST 请求。