Compose是定义和运行多容器Docker应用程序的工具。 使用Compose,您可以使用YAML文件来配置应用程序的服务。 然后,使用单个命令,您可以创建并启动配置中的所有服务。
Compose适用于所有环境:生产,开发,测试以及CI工作流程。使用Compose基本上是一个三步过程:
可以参考docker-compose官方说明详细了解:https://docs.docker.com/compose/overview/
还没有完全理解的朋友,用通俗的语言来说:
docker-compose 是用来做docker 的多容器控制,docker-compose 是一个用来把 docker 自动化的东西,有了 docker-compose 你可以把所有繁复的 docker 操作全都一条命令,自动化的完成。来看看下面这张图你也许又能更好的理解了:
从上图可以看到,这位compose哥们非常开心的把N多个容器抓在一起,根据自己的心情来编排部署。
Docker有很多优势,但对于运维或开发者来说,Docker最大的有点在于它提供了一种全新的发布机制。这种发布机制,指的是我们使用Docker镜像作为统一的软件制品载体,使用Docker容器提供独立的软件运行上下文环境,使用Docker Hub提供镜像统一协作,最重要的是该机制使用Dockerfile定义容器内部行为和容器关键属性来支撑软件运行。
Dockerfile作为整个机制的核心。这是一个非常了不起的创新,因为在Dockerfile中,不但能够定义使用者在容器中需要进行的操作,而且能够定义容器中运行软件需要的配置,于是软件开发和运维终于能够在一个配置文件上达成统一。运维人员使用同一个Dockerfile能在不同的场合下“重现”与开发者环境中一模一样的运行单元(Docker容器)出来。
先来想一下我们平时是怎么样使用docker的?把它进行拆分一下:
1、docker search 镜像,是不是先查找一个镜像;
2、docker run -itd 镜像名称 ,然后在运行这个镜像;
3、然后如果你要在运行第二个镜像、第三个镜像.....等等镜像,你是不是又要docker search、docker run运行。
上面“ docker run it 镜像名称 ”这只是最小的动作, 如果你要映射硬盘,设置nat网络或者映射端品,等等…你就要做更多的 docker 操作, 这显然是非常没有效率的,况且如果你要大规模部署,是不是觉得就很麻烦了。
但是我们写在 docker-compose.file 里面就很好了。你只需要写好后只运行一句:
docker-compose up -d
一切都是那么的简单!!!
编排,即orchestration,它根据被部署的对象之间的耦合关系,以及被部署对象环境的依赖,制定部署流程中各个动作的执行顺序,部署过程所需要的依赖文件的存储位置和获取方式,以及如何验证部署成功。这些信息都会在编排工具中以指定的格式(比如配置文件或者特定的代码)来要求运维人员定义并保存起来,从而保证这个流程能够随时在全新的环境中可靠有序地重现出来。
部署,即deployment,它是指按照编排所指定的内容和流程 ,在目标机器上执行编排指定环境初始化,存放指定的依赖和文件,运行指定的部署动作,最终按照编排中的规则来确认联署成功。
这么来解释吧,编排是一个指挥家,他的大脑里存储了整个乐曲的演奏流程,对于每一个小节每一段音乐的演奏方式、开始、结束他都了然于胸;部署就是整个乐队,他们严格按照指挥家的意图用乐器来完成乐谱的执行,在需要时开始演奏,又在适当的时机停止演奏。最终,两者通过协作就能把每一位演奏者独立的演奏通过组合、重叠、衔接来形成高品位的交响乐。
而在Compose的世界里,编排和部署的组合结果,就是一朵“容器云”。
docker-compose的调用过程扁平的像一张纸,仅用一张简单的模块图就足够解释明白,如下图所示:
首先,用户执行的docker-compose up指令调用了命令行中的启动方法。功能很简单明了,一个docker-compose.yml定义了一个docker-compose的project,docker-compose操作提供的命令行参数则作为这个project的启动参数交由project模块去处理。
其次,如果当前宿主机已经存在与该应用对应的容器,docker-compose将进行行为逻辑判断。如果用户指定可以重新启动已有服务,docker-compose就会执行service模块的容器重启方法,否则就将直接启动已有容器。这两种操作的区别在于前者会停止旧的容器,创建启动新的容器,并把旧容器移除掉。在这个过程中创建容器的各项定义参数都是从docker-compose up 指令和docker-compose.yml中传入的。
接下来,启动容器的方法也很简洁,这个方法中完成了一个Docker容器启动所需的主要参数的封装,并在container模块执行启动。该方法所支持的参数我想大多数朋友过是有所了解的。
最后,container模块会调用docker-py客户端执行向Docker daemon发起创建容器的POST请求,再往后就是Docker处理的范畴了,相信看过我这篇文章 Docker:架构拆解请 的朋友就明白了。
为了能够说明compose如何实现上述编排与部署的原理,下面和大家分享一个通过compose来编排部署LNMP服务来更好的理解它。
YAML是一种标记语言,可读性很强。类似于XML数据描述语言,语法比XML简单的多。YAML数据结构通过缩进来表示,连续的项目通过减号来表示,键值对用冒号分融,数组用括号括起来,hash用花括号括起来。详细了解的朋友可以参考 YAML百度百科 https://baike.baidu.com/item/YAML/1067697?fr=aladdin
YAML文件格式注意事项:
docker-compose中YAML常用的字段:
我们先来看下所需要的文件、目录结构是怎样的:
[root@ganbing /]# tree compose_lnmp/
compose_lnmp/
├── docker-compose.yml
├── mysql
│ ├── conf
│ │ └── my.cnf
│ └── data
├── nginx
│ ├── Dockerfile
│ ├── nginx-1.12.1.tar.gz
│ └── nginx.conf
├── php
│ ├── Dockerfile
│ ├── php-5.6.31.tar.gz
│ └── php.ini
└── wwwroot
├── index.html
└── index.php
其实看过笔者 docker:Dockerfile构建LNMP平台 这篇文章的朋友,应该对这个目录结构很熟悉,是不是发现nginx、php这两个目录和我之前写的《docker:Dockerfile构建LNMP平台》中的目录结构是一样的,无非这里多了两个目录:
mysql目录>>conf目录>>my.cnf(mysql默认配置)
mysql目录>>data目录(用于后期挂载到mysql容器)
wwwroot目录>>index.html和index.php这两个首页,用于部署成功后进行访问测试
下载最新版本安装,下载时间可能比较长
[root@ganbing ~]# curl -L https://github.com/docker/compose/releases/download/1.15.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
[root@ganbing ~]# chmod +x /usr/local/bin/docker-compose
或者用pip安装:pip install docker-compose
docker-compose用法
Usage:
docker-compose [-f...] [options] [COMMAND] [ARGS...]
docker-compose常用命令:
build 构建或重建服务
kill 杀掉容器
logs 显示容器的输出内容
port 打印绑定的开放端口
ps 显示容器
pull 拉取服务镜像
restart 重启服务
rm 删除停止的容器
run 运行一个一次性命令
scale 设置服务的容器数目
exec 在容器里搪行命令
start 开启服务
stop 停止服务
up 创建并启动容器
其实这些常用命令用docker的命令功能是一样的。
我们先来看下/compose_lnmp目录下的docker-compose.yml文件:
[root@ganbing compose_lnmp]# ls
docker-compose.yml mysql nginx php wwwroot
[root@ganbing compose_lnmp]# cat docker-compose.yml
version: '3'
services:
nginx:
hostname: nginx
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- 80:80
networks:
- lnmp
volumes:
- ./wwwroot:/usr/local/nginx/html
php:
hostname: php
build:
context: ./php
dockerfile: Dockerfile
networks:
- lnmp
volumes:
- ./wwwroot:/usr/local/nginx/html
mysql:
hostname: mysql
image: mysql:5.6
ports:
- 3306:3306
networks:
- lnmp
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/data:/var/lib/mysql
command: --character-set-server=utf8
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wordpress
MYSQL_USER: ganbing
MYSQL_PASSWORD: ganbing123
networks:
lnmp:
可以看到一份标准配置文件应该包含 version、services、networks 三大部分,共有三级标签,每一级都是缩进两个空格。下面来详细说明一下里面的内容:
version: '3'
这是定义compose的版本号为version 3,可以参考官方文档详细了解具体有哪些版本 https://docs.docker.com/compose/compose-file/
php:这个二级标签服务和下面的内容跟nginx差不多;
mysql:这个二级标签服务也和nginx、php差不多,唯一不同的是多了个images标签、还有定义了些环境变量。
image: mysql:5.6 它是通过mysql:5.6镜像来构建mysql服务器,前面nginx、php都指定了上下文通过Dockerfile来构建的。
environment:
MYSQL_ROOT_PASSWORD:定义root用户密码变量为123456;
MYSQL_DATABASE:定义了数据变量为wordpress;
MYSQL_USER:定义了普通用户变量为ganbing;
MYSQL_PASSWORD:定义了普通用户密码变量为ganbing123;
3、networks:
lnmp: 相当于执行docker network create lnmp命令了;
最后来运行docker-compose命令来启动:
[root@ganbing /]# cd compose_lnmp/
[root@ganbing compose_lnmp]# docker-compose -f docker-compose.yml up -d
来查看一下是否启动完成:
[root@ganbing compose_lnmp]# docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------
composelnmp_mysql_1 docker-entrypoint.sh --cha ... Up 0.0.0.0:3306->3306/tcp
composelnmp_nginx_1 ./sbin/nginx -g daemon off; Up 0.0.0.0:80->80/tcp
composelnmp_php_1 ./sbin/php-fpm -c /usr/loc ... Up 9000/tcp
从上面可以看出这3个服务都是UP状态,运行 docker-compose ps必须要在有docker-compose.yml文件目录下执行才可以。
在来访问一下nginx服务index.html静态页面,通过暴露的nginx 80端口来访问:
在前面我们在docker-compse.yml中的nginx服务把宿主机/wwwroot绑定到了容器/usr/local/nginx/html目录中,所以我们可以修改下宿主机中/wwwroot/index.html的内容来验证一下:
[root@ganbing /]#echo "add test" >> /compose_lnmp/wwwroot/index.html
接下来访问下index.php页面是否正常,从下面可以看到也是没问题的:
既然用docker-compose编排部署LNMP平台搞定了,只要你弄懂了原理和方法,用docker-compose编排部署其它服务也是一样的,只不过是思路的问题。
大家想想,仅仅使用Compose,就可以构建自己的容器云吗?答案显然是否定的。docker-compose解决的问题局限在“编排”二字,甚至连“部署”范畴都涉足甚少,而在一个能够服务于大众的云平台中,编排与部署也仅仅是其中的一个组成部分而已。来一起分析一下它的局限制会有哪些:
那么,是否有一种能够提供完善的面向服务器集群的Docker编排和部署方案呢?Docker官方给出的答案是Compose同Machine和Swarm联动,其实还有大家近期经常听到了kubernetes(k8s)。后期笔者会更新出这些内容和大家一起来讨论。
喜欢我的文章,请点击最上方右角处的《关注》支持一下!
转载于:https://blog.51cto.com/ganbing/2083806