目录
Docker Compose
Compose的优点
编排和部署
Compose原理
Compose应用案例
安装docker-ce
阿里云镜像加速器
安装docker-compose
docker-compose用法
Yaml简介
验证LNMP环境
Docker Compose
Docker Compose 的前身是 Fig,它是一个定义及运行多个 Docker 容器的工具。可以使用YAML文件来配置应用程序的服务。然后,使用单个命令,您可以创建并启动配置中的所有服务。Docker Compose 会通过解析容器间的依赖关系(link, 网络容器 -net-from 或数据容器 -volume-from)按先后顺序启动所定义的容器。
Compose 是 Docker 的服务编排工具,主要用来构建基于 Docker 的复杂应用,Compose 通过一个配置文件来管理多个 Docker 容器,非常适合组合使用多个容器进行开发的场景。
Compose适用于所有环境:生产,开发,测试以及CI工作流程。使用Compose基本上是一个三步过程:
- 使用Dockerfile定义应用程序的环境,以便在任何地方进行复制。
- 在docker-compose.yml中定义组成应用程序的服务,以便它们可以在隔离的环境中一起运行。
- 运行docker-compose开始并运行整个应用程序。
docker-compose官方文档:Docker Compose overview | Docker Documentation
docker-compose 是用来做docker 的多容器控制,有了 docker-compose 你可以把所有繁复的 docker 操作全都用一条命令自动化完成。从上图可以看到,这位compose非常开心的把N多个容器抓在一起,根据自己的心情来编排部署。
Docker对于运维或开发者来说,Docker最大的优点在于它提供了一种全新的发布机制。这种发布机制,指的是我们使用Docker镜像作为统一的软件制品载体,使用Docker容器提供独立的软件运行上下文环境,使用Docker Hub提供镜像统一协作,最重要的是该机制使用Dockerfile定义容器内部行为和容器关键属性来支撑软件运行。
Dockerfile作为整个机制的核心。在Dockerfile中不但能够定义使用者在容器中需要进行的操作,而且能够定义容器中运行软件需要的配置,于是软件开发和运维终于能够在一个配置文件上达成统一。运维人员使用同一个Dockerfile能在不同的场合下“重现”与开发者环境中一模一样的运行单元(Docker容器)出来。
Compose的优点
先来了解一下我们平时是怎么样使用docker的?把它进行拆分一下:
1、docker search 镜像,是不是先查找一个镜像;
2、docker run -itd 镜像名称 ,然后在运行这个镜像;
3、然后如果你要在运行第二个镜像、第三个镜像.....等等,你是不是又要docker search、docker run运行。
上面“ docker run -itd 镜像名称 ”这只是最小的动作,如果你要映射硬盘,设置nat网络或者映射端口等等。就要做更多的 docker 操作,这显然是非常没有效率的,况且如果你要大规模部署,是不是觉得就很麻烦了。
但是我们写在docker-compose里面就很好了。你只需要写好后只运行一句:
docker-compose up -d
编排和部署
编排,即orchestration,它根据被部署的对象之间的耦合关系,以及被部署对象环境的依赖,制定部署流程中各个动作的执行顺序,部署过程所需要的依赖文件的存储位置和获取方式,以及如何验证部署成功。这些信息都会在编排工具中以指定的格式(比如配置文件或者特定的代码)来要求运维人员定义并保存起来,从而保证这个流程能够随时在全新的环境中可靠有序地重现出来。
部署,即deployment,它是指按照编排所指定的内容和流程 ,在目标机器上执行编排指定环境初始化,存放指定的依赖和文件,运行指定的部署动作,最终按照编排中的规则来确认联署成功。
这么来解释吧,编排是一个指挥家,他的大脑里存储了整个乐曲的演奏流程,对于每一个小节每一段音乐的演奏方式、开始、结束他都了然于胸;部署就是整个乐队,他们严格按照指挥家的意图用乐器来完成乐谱的执行,在需要时开始演奏,又在适当的时机停止演奏。最终,两者通过协作就能把每一位演奏者独立的演奏通过组合、重叠、衔接来形成高品位的交响乐。
Compose原理
docker-compose的调用过程扁平的像一张纸,仅用一张简单的模块图就足够解释明白,如下图所示:
首先,用户执行的docker-compose up -d指令调用了命令行中的启动方法。功能很简单明了,一个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服务来更好的理解它。
Compose应用案例
安装docker-ce
[root@localhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@localhost ~]# yum -y install yum-utils device-mapper-persistent-data lvm2
[root@localhost ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# ls /etc/yum.repos.d/
backup Centos-aliyun.repo CentOS-Media.repo docker-ce.repo
[root@localhost ~]# yum -y install docker-ce
[root@localhost ~]# systemctl start docker
[root@localhost ~]# systemctl enable docker
阿里云镜像加速器
阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台欢迎登录阿里云,全球领先的云计算及人工智能科技公司,阿里云为200多个国家和地区的企业、开发者和政府机构提供云计算基础服务及解决方案。阿里云云计算、安全、大数据、人工智能、企业应用、物联网等云计算服务。https://cr.console.aliyun.com/
[root@localhost ~]# cat << END > /etc/docker/daemon.json
{
"registry-mirrors":[ "https://nyakyfun.mirror.aliyuncs.com" ]
}
END
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker
[root@localhost ~]# docker version
Client: Docker Engine - Community
Version: 19.03.8
API version: 1.40
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:27:04 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.8
API version: 1.40 (minimum version 1.12)
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:25:42 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
安装docker-compose
docker-compose提取链接:https://pan.baidu.com/s/1ArQGMU0MYW5aILUHkqokXQ?pwd=1zuw
提取码:1zuw
[root@compose ~]# rz #上传docker-compose文件
[root@compose ~]# mv docker-compose /usr/local/bin/
mv:是否覆盖"/usr/local/bin/docker-compose"? y
[root@compose ~]# chmod +x /usr/local/bin/docker-compose
[root@compose ~]# docker-compose --version
docker-compose version 1.21.1, build 5a3f1a3
docker-compose用法
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose 常用选项:
- --verbose 输出更多调试信息。
- --version 打印版本并退出。
- -f, --file FILE 使用特定的 compose 模板文件,默认为docker-compose.yml。
- -p, --project-name NAME 指定项目名称,默认使用目录名称。
docker-compose常用命令:
- build 构建或重建服务
- kill 杀掉容器
- logs 显示容器的输出内容
- port 打印绑定的开放端口
- ps 显示容器
- pull 拉取服务镜像
- restart 重启服务
- rm 删除停止的容器
- run 运行一个一次性命令
- scale 设置服务的容器数目
- exec 切换到容器内
- start 开启服务
- stop 停止服务
- up 创建并启动容器
其实这些常用命令用docker的命令功能是一样的。
Yaml简介
YAML是一种标记语言,可读性很强。类似于XML数据描述语言,语法比XML简单的多。YAML数据结构通过缩进来表示,连续的项目通过减号来表示,键值对用冒号分割,数组用括号括起来,hash用花括号括起来。
YAML文件格式注意事项:
在缩排中空白字符的数目并不是非常重要,只要相同阶层的元素左侧对齐就可以了(不过不能使用TAB字符);
- 通常开头缩进2个空格;
- 字符的后面缩进1个空格,比如冒号、逗号、横杆;
- 支持#注释;
- 允许在文件中加入选择性的空行,以增加可读性;
docker-compose中YAML常用的字段:
目录结构
compose_lnmp-190606.zip文件提取链接:https://pan.baidu.com/s/1UqA6L9O6-tTkBcUyf-v3zQ?pwd=7bkk
提取码:7bkk
[root@localhost ~]# mkdir compose_lnmp
[root@localhost ~]# cd compose_lnmp/
[root@localhost compose_lnmp]# rz #上传compose_lnmp-190606.zip文件
[root@localhost compose_lnmp]# unzip compose_lnmp-190606.zip
Archive: compose_lnmp-190606.zip
inflating: compose_lnmp/nginx/nginx.conf
inflating: compose_lnmp/docker-compose.yml
creating: compose_lnmp/mysql/
creating: compose_lnmp/mysql/conf/
inflating: compose_lnmp/mysql/conf/my.cnf
creating: compose_lnmp/mysql/data/
inflating: compose_lnmp/nginx/Dockerfile
inflating: compose_lnmp/nginx/nginx-1.12.1.tar.gz
extracting: compose_lnmp/nginx/run.sh
creating: compose_lnmp/php/
inflating: compose_lnmp/php/Dockerfile
inflating: compose_lnmp/php/php-5.6.39.tar.gz
inflating: compose_lnmp/php/php.ini
creating: compose_lnmp/wwwroot/
extracting: compose_lnmp/wwwroot/index.html
extracting: compose_lnmp/wwwroot/index.php
[root@localhost compose_lnmp]# tree
.
├── compose_lnmp
│ ├── docker-compose.yml
│ ├── mysql
│ │ ├── conf
│ │ │ └── my.cnf
│ │ └── data
│ ├── nginx
│ │ ├── Dockerfile
│ │ ├── nginx-1.12.1.tar.gz
│ │ ├── nginx.conf
│ │ └── run.sh
│ ├── php
│ │ ├── Dockerfile
│ │ ├── php-5.6.39.tar.gz
│ │ └── php.ini
│ └── wwwroot
│ ├── index.html
│ └── index.php
└── compose_lnmp-190606.zip
7 directories, 12 files
编写compose文件
[root@compose 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
ports:
- 9000:9000
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: user
MYSQL_PASSWORD: user123
networks:
lnmp:
可以看到一份标准配置文件应该包含 version、services、networks 三大部分,共有三级标签,每一级都是缩进两个空格。下面来详细说明一下里面的内容:
version: '3' 这是定义compose的版本号为version 3,可以参考官方文档详细了解具体有哪些版本 Overview | Docker Documentation
services:
nginx:这是services下面的二级标签,名字用户自己定义,它将是服务运行后的名称;
hostname: nginx 这是定义容器的主机名,将写入到/etc/hostname中;
build:
context: ./nginx 指定nginx服务的上下文路径;
dockerfile:Dockerfile 指定通过上面指定路径中的Dockerilfe来构建;
ports:
- 80:80 端口映射没什么好说的;
networks:
-lnmp 指定的网络环境
volumes:把宿主机的/wwwroot目录绑定到容器中的/usr/local/nginx/html目录;
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:定义了普通用户变量为user;
MYSQL_PASSWORD:定义了普通用户密码变量为user123;
3、networks:
lnmp: 相当于执行docker network create lnmp命令了;
最后来运行docker-compose命令来启动:
[root@localhost ~]# cat centos-7-x86_64.tar.gz | docker import - centos:7
sha256:7ed67541d15fe31090ac0cf8528c5a05c8f6ecff3a17a57c6820004ecd823240
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 7ed67541d15f 17 seconds ago 589MB
[root@localhost compose_lnmp]# docker-compose -f docker-compose.yml up -d
Status: Downloaded newer image for mysql:5.6
Creating compose_lnmp_mysql_1 ... done
Creating compose_lnmp_nginx_1 ... done
Creating compose_lnmp_php_1 ... done
[root@localhost compose_lnmp]# docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------
compose_lnmp_mysql_1 docker-entrypoint.sh --cha Up 0.0.0.0:3306->3306/tcp,:::3
... 306->3306/tcp
compose_lnmp_nginx_1 /run.sh Up 0.0.0.0:80->80/tcp,:::80->8
0/tcp
compose_lnmp_php_1 ./sbin/php-fpm -c /usr/loc Up 0.0.0.0:9000->9000/tcp,:::9
... 000->9000/tcp
验证LNMP环境
客户端使用浏览器验证 docker-compose 创建的 lnmp 环境
PS:如果访问报 Access denined.,手动进入 nginx 容器添加读权限。
docker-compose解决的问题局限在“编排”二字,甚至连“部署”范畴都涉足甚少,而在一个能够服务于大众的云平台中,编排与部署也仅仅是其中的一个组成部分而已。来一起分析一下它的局限制会有哪些:
- docker-compse是面向单宿主机部署的,这是一种部署能力的欠缺。在更多的场合下,管理员需要面对大量物理服务器(或者虚拟机),这时如果要实现基于docker-compose的容器自动化编排与部署,管理员就得借助成熟的自动化运维工具(ansible、puppet、chef、saltstack)来负责管理多个目标主机,将docker-compose所需的所有资源(配置文件、用户代码)交给目标主机,然后在目标主机上执行docker-compose指令。
- 同样网络和存储也比较棘手,Docker不能提供跨宿主机的网络,完全面向Docker daemon的docker-compose当然也不支持。这意味着管理员必须部署一套类似于Open vSwich的独立网络工具,而且管理员还需要完成集成工作。当好不容易把容器编排都安排妥当之后,又会发现容器还处在内网环境中,于是负载均衡、服务发现等一堆问题就面临而来了,这些问题很快能消耗掉工程师所有的耐心。
那么,是否有一种能够提供完善的面向服务器集群的Docker编排和部署方案呢?Docker官方给出的答案是Compose同Machine和Swarm联动,其实还有大家近期经常听到了kubernetes(k8s)。