Docker集群管理之Docker Compose(docker—compose)
wptr33 2025-04-07 20:04 15 浏览
前言:在上一篇《Docker集群管理之Docker Machine》中,我们通过源码分析了解了Docker Machine的工作原理,使用者可以通过Docker Machine的一条命令在任意支持的平台创建一个Docker主机,并能集中管理这些主机。Docker主机创建好之后,接下来就该考虑Docker容器部署的问题了。本篇中我们将通过分析Docker Compose的源码,了解Docker Compose的工作原理。
与容器技术同样受到关注的微服务架构也在潜移默化的改变着应用的部署方式,其提倡将应用分割成一系列细小的服务,每个服务专注于单一业务功能,服务之间采用轻量级通信机制相互沟通。同时数据库解决方案也在发生在变化,多种持久化混合方案(Polyglot Persistence)提倡将数据存放在最适合的数据库解决方案中,而传统的数据库解决方案将数据存在在同一个数据库服务中。服务数量的增加也就意味着容器数量的增多,逐渐增加的容器数量为容器部署,运行及管理带来了挑战。Docker Compose的出现解决多个容器部署的问题并提高了多个容器解决方案的可移植性。
Docker Compose的前身是Fig,它是一个定义及运行多个Docker容器的工具。使用Docker Compose你只需要在一个配置文件中定义多个Docker容器,然后使用一条命令将多个容器启动,Docker Compose会通过解析容器件的依赖关系(link, 网络容器 –net-from或数据容器 –volume-from)按先后顺序启动所定义的容器。
安装Docker Compose
可以通过下载二进制可执行文件的方式安装Docker Compose
Docker Compose的工作原理
Docker Compose将所管理的容器分为三层,工程(project),服务(service)以及容器(contaienr)。Docker Compose运行的目录下的所有文件(docker-compose.yml, extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例,Docker Compose并没有解决负载均衡的问题,因此需要借助其他工具实现服务发现及负载均衡。
Docker Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。以下是一个简单的配置文件:
其定义了两个服务web和redis。web服务的镜像需要在当前目录实时构建,其容器运行时需要在宿主机开放端口5000并映射到容器端口5000,并且挂载存储卷/code以及关联服务redis。redis服务通过镜像redis启动。
Docker Compose是由python语言实现的,它通过调用docker-py库(可参考
https://github.com/docker/docker-py)与docker engine通信实现构建docker镜像,启动停止docker容器等。Docker-py库调用docker remote API(可参考
https://docs.docker.com/reference/api/docker_remote_api/)与Docker Daemon通信,可通过DOCKER_HOST配置本地或远程Docker Daemon的地址。
下面我们通过分析docker-compose最复杂的命令up的源码来了解一下docker compose的工作原理。
通过命令docker-compose up -d启动以上docker-compose.yml定义的服务。
我们可以看到redis服务先于web服务创建,这是因为docker-compose解析到服务间的依赖关系,web服务依赖于redis服务,所以进行了排序。我们来看一下docker compose up的工作流程。
1. 工程初始化 – 解析配置文件(包括docker-compose.yml,外部配置文件extends files,环境变量配置文件env_file),并将每个服务的配置转换成python字典,初始化docker-py客户端用于与本地或远端的docker engine通信。
2. 根据docker-compose的命令参数将命令分发给相应的处理函数,此处为up
3. 调用project类的up函数,得到当前工程中的所有服务,并根据服务的依赖性(links,external links – 本工程或docker-compose之外的容器,多用于多项目共用容器,网络容器net-from以及数据容器volume-from)进行排序并去掉重复出现服务(此情况可因某服务被其他多个服务依赖所造成)
4. Docker Compose使用labels标记启动的容器
使用docker inspect可以看到一个通过docker compose启动的容器被添加了一些compose使用的标记
5. Docker Compose通过compose工程名以及服务名从docker engine获取当前所有含有此标记的容器以检查当前工程所包含的服务状态,根据当前状态为每个服务制定接下来的动作。
a. 若容器不存在,则服务动作设置为创建(create)
b. 若容器存在但设置不允许重建,则服务动作设置为启动(start)
c. 若容器配置发生变化(config-hash)或者设置强制重建标志,则服务动作设置为重建(recreate)
d. 若容器状态为停止,则服务动作设置为启动(start)
e. 若容器状态为运行但其依赖容器需要重建,则服务状态设置为重建(recreate)
f. 若容器状态为运行其无配置改变则不作操作
6. 根据每个服务不同的动作执行不同的操作
服务动作为创建
a. 检查镜像是否存在(调用docker-py client inspect函数从本地或远程的docker engine获取镜像信息)。若镜像不存在,则检查配置文件中关于镜像的定义。如果在配置文件中设置为build则调用docker-py build函数与docker engine通信完成docker build的功能。如果在配置文件中设置为image则通过docker-py pull函数与docker engine通信完成docker pull的功能。
b. 获取当前服务中容器的配置信息,如端口,存储卷,主机名,使用镜像环境变量等配置的信息。若在配置中指定本服务必须与某个服务在同一台主机(previous_container,用于集群)则在环境变量中设置affinity:container=。通过docker-py与docker engine通信创建并启动容器。
服务动作为重建
a. 停止当前的容器
b. 将现有的容器重命名,这样数据卷在原容器被删除前就可以拷贝到新创建的容器中了
c. 创建并启动新容器,previsous_container设置为原容器确保其运行在同一台主机(存储卷挂载)
d. 删除旧容器
服务动作为启动则启动停止的容器
7. 若docker-compose up没有指明-d即前台运行,则将所有各个容器的输出汇聚打印
8. 注册信号SIGINT处理函数,若收到信号SIGINT则并行杀掉所有容器
到此为止docker-compose up的命令执行完毕,docker-compose.yml文件中定义的服务 全部启动。
Docker Compose的命令主要分为以下几类
管理服务:up/start/scale/stop/restart/rm/kill
管理镜像:build/pull
查看服务运行状态:ps/port
打印运行中的服务log:logs
在一个服务中执行一个一次性命令:run
以上这些命令都是通过label标记来过滤当前工程里的容器,然后调用docker-py库调用Docker remote API与docker engine通信控制容器。
Docker Compose是一个部署多个容器的简单但是非常必要的工具,它使你使用一条简单的命令部署多个容器。Docker Compose在实际工作中非常有价值,其大大简化了多容器的部署过程,避免了在不同环境运行多个重复步骤所带来的错误可能,使多容器移植变得简单可控。从其Roadmap可以看出,Docker Compose的目标是做一个生产环境可用的工具,包括服务回滚,多环境支持(dev/test/staging/prod),支持在线服务部署升级,防止服务中断并且监控服务使其始终运行在正确的状态。Roadmap中的另一个目标是更好的与Docker Swarm集成,目前版本存在的主要问题是无法保证处于多个主机的容器间正常通信因为目前不支持跨主机间容器通信,我们相信新的Docker网络实现将会解决这一问题。另一个问题是在Docker Compose中定义构建的镜像只存在在一台Docker Swarm主机上,无法做到多主机共享,因此目前需要手动构建镜像并上传到一个镜像仓库使多个Docker Swarm主机可以访问并下载镜像。相信随着Docker Compose的完善,其必将取代docker run成为开发者启动docker容器的首选。
作者简介:杜航,Websense云基础架构组开发经理,专注于Openstack和Docker。灵雀云资深用户。
预告:9月1日晚上8点整,杜航将通过在线培训的方式详细探讨《Docker集群管理三剑客》,报名地址请
相关推荐
- 每天一个编程技巧!掌握这7个神技,代码效率飙升200%
-
“同事6点下班,你却为改BUG加班到凌晨?不是你不努力,而是没掌握‘偷懒’的艺术!本文揭秘谷歌工程师私藏的7个编程神技,每天1分钟,让你的代码从‘能用’变‘逆天’。文末附《Python高效代码模板》,...
- Git重置到某个历史节点(Sourcetree工具)
-
前言Sourcetree回滚提交和重置当前分支到此次提交的区别?回滚提交是指将改动的代码提交到本地仓库,但未推送到远端仓库的时候。...
- git工作区、暂存区、本地仓库、远程仓库的区别和联系
-
很多程序员天天写代码,提交代码,拉取代码,对git操作非常熟练,但是对git的原理并不甚了解,借助豆包AI,写个文章总结一下。Git的四个核心区域(工作区、暂存区、本地仓库、远程仓库)是版本控制的核...
- 解锁人生新剧本的密钥:学会让往事退场
-
开篇:敦煌莫高窟的千年启示在莫高窟321窟的《降魔变》壁画前,讲解员指着斑驳色彩说:"画师刻意保留了历代修补痕迹,因为真正的传承不是定格,而是流动。"就像我们的人生剧本,精彩章节永远...
- Reset local repository branch to be just like remote repository HEAD
-
技术背景在使用Git进行版本控制时,有时会遇到本地分支与远程分支不一致的情况。可能是因为误操作、多人协作时远程分支被更新等原因。这时就需要将本地分支重置为与远程分支的...
- Git恢复至之前版本(git恢复到pull之前的版本)
-
让程序回到提交前的样子:两种解决方法:回退(reset)、反做(revert)方法一:gitreset...
- 如何将文件重置或回退到特定版本(怎么让文件回到初始状态)
-
技术背景在使用Git进行版本控制时,经常会遇到需要将文件回退到特定版本的情况。可能是因为当前版本出现了错误,或者想要恢复到之前某个稳定的版本。Git提供了多种方式来实现这一需求。...
- git如何正确回滚代码(git命令回滚代码)
-
方法一,删除远程分支再提交①首先两步保证当前工作区是干净的,并且和远程分支代码一致$gitcocurrentBranch$gitpullorigincurrentBranch$gi...
- [git]撤销的相关命令:reset、revert、checkout
-
基本概念如果不清晰上面的四个概念,请查看廖老师的git教程这里我多说几句:最开始我使用git的时候,我并不明白我为什么写完代码要用git的一些列指令把我的修改存起来。后来用多了,也就明白了为什么。gi...
- 利用shell脚本将Mysql错误日志保存到数据库中
-
说明:利用shell脚本将MYSQL的错误日志提取并保存到数据库中步骤:1)创建数据库,创建表CreatedatabaseMysqlCenter;UseMysqlCenter;CREATET...
- MySQL 9.3 引入增强的JavaScript支持
-
MySQL,这一广泛采用的开源关系型数据库管理系统(RDBMS),发布了其9.x系列的第三个更新版本——9.3版,带来了多项新功能。...
- python 连接 mysql 数据库(python连接MySQL数据库案例)
-
用PyMySQL包来连接Python和MySQL。在使用前需要先通过pip来安装PyMySQL包:在windows系统中打开cmd,输入pipinstallPyMySQL ...
- mysql导入导出命令(mysql 导入命令)
-
mysql导入导出命令mysqldump命令的输入是在bin目录下.1.导出整个数据库 mysqldump-u用户名-p数据库名>导出的文件名 mysqldump-uw...
- MySQL-SQL介绍(mysql sqlyog)
-
介绍结构化查询语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统,可以使用相同...
- MySQL 误删除数据恢复全攻略:基于 Binlog 的实战指南
-
在MySQL的世界里,二进制日志(Binlog)就是我们的"时光机"。它默默记录着数据库的每一个重要变更,就像一位忠实的史官,为我们在数据灾难中提供最后的救命稻草。本文将带您深入掌握如...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
-
- 每天一个编程技巧!掌握这7个神技,代码效率飙升200%
- Git重置到某个历史节点(Sourcetree工具)
- git工作区、暂存区、本地仓库、远程仓库的区别和联系
- 解锁人生新剧本的密钥:学会让往事退场
- Reset local repository branch to be just like remote repository HEAD
- Git恢复至之前版本(git恢复到pull之前的版本)
- 如何将文件重置或回退到特定版本(怎么让文件回到初始状态)
- git如何正确回滚代码(git命令回滚代码)
- [git]撤销的相关命令:reset、revert、checkout
- 利用shell脚本将Mysql错误日志保存到数据库中
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)