Docker Compose 原理
Docker 的优势非常明显,尤其是对于开发者来说,它提供了一种全新的软件发布机制。也就是说使用 docker 镜像作为软件产品的载体,使用 docker 容器提供独立的软件运行上下文环境,使用 docker hub 等提供镜像的集中管理,这其中最重要的是使用 Dockerfile 定义容器的内部行为和关键属性来支持软件运行。但是实际的生产环境往往需要定义数量庞大的 docker 容器,并且容器之间具有错综复杂的联系。手动的记录和配置这些复杂的容器关系,不仅效率低下而且容易出错。所以,我们迫切需要一种像 Dockerfile 定义 docker 容器一样能够定义容器集群的编排和部署工具。于是,Docker Compose 出现了(其实应该说 Fig 出现了,docker 收购了 Fig 并改名为 compose)。
Dockerfile 重现一个容器,compose 则用来重现容器的集群。
说明:本文的演示环境为 ubuntu 16.04。
编排和部署
编排(orchestration)
编排指根据被部署的对象之间的耦合关系,以及被部署对象对环境的依赖,制定部署流程中各个动作的执行顺序,部署过程所需要的依赖文件和被部署文件的存储位置和获取方式,以及如何验证部署成功。这些信息都会在编排工具中以指定的格式(比如配置文件或特定的代码)来要求运维人员定义并保存起来,从而保证这个流程能够随时在全新的环境中可靠有序地重现出来。
部署(deployment)
部署是指按照编排所指定的内容和流程,在目标机器上执行环境初始化,存放指定的依赖文件,运行指定的部署动作,最终按照编排中的规则来确认部署成功。
所以说,编排是一个指挥家,他的大脑里存储了整个乐曲此起彼伏的演奏流程,对于每一个小节每一段音乐的演奏方式都了然于胸。而部署就是整个乐队,他们严格按照指挥家的意图用乐器来完成乐谱的执行。最终,两者通过协作就能把每一位演奏者独立的演奏通过组合、重叠、衔接来形成高品位的交响乐。这也是 docker compose 要完成的使命。
Compose 原理
笔者在前文《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=

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

右上角的 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 模块处理。
然后,如果当前宿主机已经存在与该应用对应的容器,docker-compose 则进行行为逻辑判断。如果用户指定可以重新启动已有服务,docker-compose 就会执行 service 模块的容器重启方法,否则就直接启动已有容器。这两种操作的区别在于前者会停止旧的容器,创建并启动新的容器,并把旧容器移除掉。在这个过程中创建容器的各项自定义参数都是从 docker-compose up 命令和 docker-compose.yml 中传入的。
接下来,启动容器的方法也很简洁,这个方法中完成了一个 docker 容器启动所需的主要参数的封装,并在 container 模块执行启动。
最后,contaier 模块会调用 docker-py 客户端来执行向 docker daemon 发起创建容器的 POST 请求。
由此可见 docker-compose 工作的整体流程非常清晰、简洁!
重新启动 services
前面我们提到当前宿主机已经存在与该应用对应的容器,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 容器和容器云》
Docker Compose 原理的更多相关文章
- Istio入门实战与架构原理——使用Docker Compose搭建Service Mesh
本文将介绍如何使用Docker Compose搭建Istio.Istio号称支持多种平台(不仅仅Kubernetes).然而,官网上非基于Kubernetes的教程仿佛不是亲儿子,写得非常随便,不仅缺 ...
- Docker Compose 部署 Redis 及原理讲解 | 懒人屋
原文:Docker Compose 部署 Redis 及原理讲解 | 懒人屋 Docker Compose 部署 Redis 及原理讲解 4.4k 字 16 分钟 2019-10-1 ...
- Docker 核心技术之Docker Compose
Docker Compose 简介 Docker Compose是什么? Docker Compose是一个能一次性定义和管理多个Docker容器的工具. 详细地说: Compose中定义和启动的每一 ...
- Docker Compose 之进阶篇
笔者在前文<Docker Compose 简介>和<Dcoker Compose 原理>两篇文章中分别介绍了 docker compose 的基本概念以及实现原理.本文我们将继 ...
- Docker Compose(八)
Docker Compose 是Docker官方编排(Orchstration)项目之一,负责快速在集群中部署分布式应用. Dockerfile可以让用户管理一个单独的应用容器:而Compose则 ...
- Docker学习笔记之编写 Docker Compose 项目
0x00 概述 通过阅读之前的小节,相信大家对 Docker 在开发中的应用已经有了一定的了解.作为一款实用的软件,我们必须回归到实践中来,这样才能更好地理解 Docker 的实用逻辑和背后的原理.在 ...
- 控制Docker Compose的启动顺序的一个思路
起源 守护进程daemon 从守护进程的角度看Docker Compose Docker的解决方案 思路 代码 结果 起源 Docker Compose提供了一个depends_on参数. https ...
- 使用Docker Compose搭建Service Mesh
使用Docker Compose搭建Service Mesh 本文将介绍如何使用Docker Compose搭建Istio.Istio号称支持多种平台(不仅仅Kubernetes).然而,官网上非基于 ...
- Docker Compose编排工具部署lnmp实践及理论(详细)
目录 一.理论概述 编排 部署 Compose原理 二.使用docker compose 部署lnmp 三.测试 四.总结 一.理论概述 Docker Compose是一个定义及运行多个Docker容 ...
随机推荐
- BZOJ 3864
dp of dp 我就是来贴个代码 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a ...
- 20181117-python第二章学习小结-part1
什么是二进制,十进制如何转化成二进制. 在python上可使用简单的函数进行转化,bin() 数据量的基本关系: 1bit 就是0/1的一个单位 1bytes = 8bit #1个字节,就是一 ...
- 20181115 python-第一章学习小结part2
Python基本知识 变量,用来存储中间计算结果,在后面可进行调用被使用的东西,叫做变量. 变量的命名规则: 字母,数字,下划线组合 不能用数字开头 常见的关键字不能用啊 常量,不会变的量,称作常量. ...
- 机器学习——KNN算法(k近邻算法)
一 KNN算法 1. KNN算法简介 KNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分 ...
- Android Studio 错误: 非法字符: '\ufeff'
右下角:选UTF-8 convert一下,再重新编译..不知道为什么,本来好像就是UTF-8好奇怪. 还看到一个方法但我没试过,放在这里万一下次又遇见了这样的问题呢 右下角将UTF-8 convert ...
- Cloud Native 云化架构阅读笔记
一• Cloud Native CloudNative是什么? Cloud Native翻译为云原生,是Matt Stine提出的一个概念,它是一个思想的集合,包括DevOps.持续交付(Contin ...
- node环境使用multer搭建一个图片接收服务器
为了测试图片上传插件的上传功能是否好用,最近尝试搭建了一个接收图片的服务器,因为图片上传的编码格式是form-data,所以我选择使用express+multer,实现过程中发现有几个需要注意的地方, ...
- [Swift]LeetCode343. 整数拆分 | Integer Break
Given a positive integer n, break it into the sum of at least two positive integers and maximize the ...
- [Swift]LeetCode387. 字符串中的第一个唯一字符 | First Unique Character in a String
Given a string, find the first non-repeating character in it and return it's index. If it doesn't ex ...
- [Swift]LeetCode474. 一和零 | Ones and Zeroes
In the computer world, use restricted resource you have to generate maximum benefit is what we alway ...