目录
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 5a3f1a3docker-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)。





![[数据集][目标检测]遛狗不牵绳数据集VOC格式-1980张](https://i0.hdslb.com/bfs/archive/b218ed1884b250be57b2ee3ae09d26814eb427c8.jpg@100w_100h_1c.png@57w_57h_1c.png)













