Docker 提供了一种全新的软件运行和发布机制: (1) 以 docker 镜像作为软件的载体。(2) 以 docker 容器[基于镜像的运行实例]来提供独立的软件运行上下文环境。 (3)通过 docker hub 等提供镜像的集中管理。(4) 使用 Dockerfile 定义容器的内部行为和关键属性来支持软件运行。

但是实际的生产环境中,一个项目或者工程往往需要各种不同的软件或程序,也就是说需要数量庞大的 docker 容器,并且容器之间具有错综复杂的联系。手动的记录和配置这些复杂的容器关系,不仅效率低下而且容易出错。所以我们希望可以像使用 Dockerfile 定义容器那样管理不同的 docker 容器,于是有了 docker compose。

Compose 是 docker 提供的一个命令行工具,用来定义和运行由多个容器组成的应用。使用 compose,我们可以通过 YAML 文件声明式的定义应用程序的各个服务,并由单个命令完成应用的创建和启动。

Compose 原理

Compose 中两个最重要的概念是ProjectService

Project

通过 docker compose 管理的一个项目被称为一个 project,它是由一组关联的应用容器组成的一个完整的业务单元。简单点说就是一个 docker-compose.yml 文件定义一个 project。

Service

Service 是指运行一个应用的容器,但是在实际中,一个 Project 可以包括一个或多个运行相同镜像的容器。相同镜像的容器个数可以通过 docker-compose up 命令的 –scale 选项来完成,也就是指定某个 service 运行的容器个数,例如docker-compose up -d --scale redis=2,就是运行两个 redis 容器。

Running

Compose 的使用方式非常简单,总共分三步:

  • 定义 Dockerfile

  • 定义 docker-compose.yml

  • 运行 docker-compose up

首先,用户执行的 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 请求。

默认情况下 compose 启动容器的顺序是不确定的,但是有些场景下我们希望能够控制容器的启动顺序。我们可以通过 depends_on 来解决有依赖关系的容器的启动顺序问题