联调环境快速部署——基于docker-compose的CI/CD实践

项目地址: github.com/xiongwilee/…php

基本特性:nginx

  1. 快捷部署多人nginx+php的开发测试环境,也能够扩展构建其余语言;
  2. 基于Docker和docker-compose,不依赖K8S等高级编排工具,成本低廉、部署简单;
  3. Docker内置集成jenkins,一键添加开发测试角色,无需额外配置;
  4. 支持微服务架构,适用于小公司or敏捷项目团队,也能够做为Docker学习入门的case

1、背景

在角色分工明确的团队里,什么样的条件才算是最优雅的联调和测试环境?在大厂里确定都有不少高级的解决方案,好比这些:git

大型团队的合做框架下,必须依赖更复杂的DevOps架构(参考:DevOps详解)。但对于成员很少、负责的Web项目工程量也不大的团队,面临的问题确定也更单纯:github

  1. 先后端角色工程解耦,开发环境分离;
  2. 工程师只关注业务逻辑自己,持续集成;
  3. 环境和角色一键建立、一键更新、一键销毁,环境之间不受影响;

即使是只有这些需求,在以往的“开发机”的联调环境里,一旦须要添加开发或者测试人员,或者须要更新nginx的配置,再或者须要更新PHP、Nodejs的版本……对于测试环境的维护来讲都是很痛苦的。web

2、快速开始

注意: 当前部署方案仅依赖:Docker,Docker-compose,gitdocker

一、下载代码

$ git clone https://github.com/xiongwilee/docker-compose-boilerplate.git
复制代码

二、添加测试角色demo

$ cd docker-compose
$ sh build.sh -u demo -m admin:master
复制代码

此时,在app/会建立demo目录,在nginx/conf.d会建立demo.conf文件。后端

三、启动服务

$ docker-compose up -d
复制代码

此时,再执行docker-compose ps会发现建立了三个镜像。而后,配置hosts使sample.demo.testdomain.com指向当前机器,而后访问http://sample.demo.testdomain.com 返回phpinfo()信息,说明建立成功。bash

3、部署架构说明

TIPS: 这个方案仅适用于小公司or敏捷项目团队联调测试环境的部署,同时也能够做为Docker学习入门的case,并不适用于有必定规模的生产环境。markdown

在“开发机”上仅仅安装docker、docker-compose、git以后就能跑起来Nginx、PHP的应用,固然得益于docker容器化的思想。其实这个的实现也仅仅利用了容器化的这个特性,最终docker-compose打包的整个服务会长驻内存,无需太多的管理成本。架构

最终的实现还具有两个特色:

  1. 基于这个实现的boilerplate你能够轻易的迁移到其余项目,以及其余语言;
  2. 每一个sample管理每一个应用的仓储地址、环境变量配置、更新代码后的钩子等操做;

其实现原理为:经过脚本文件,管理docker-compose隐射到宿主机的配置、源码,同时将docker-compose暴露出来以实现服务的管理。架构图以下:

一、docker-compose配置文件:docker-compose.yml

先看docker-compose的配置文件docker-compose.yml(篇幅缘由,删掉了一部分配置):

version: '3'
services:
    # 全部的PHP环境构建在app容器里
 php:
 build: ./php
 expose:
 - "9000"
    # nginx容器
 nginx:
 build: ./nginx
        # 端口映射
 ports:
 - "80:80"
        # 依赖关系声明,先跑php全部服务
 depends_on:
 - "php"
    # jenkins容器
 jenkins:
 image: jenkins:latest
 ports:
 - "8080:8080"
 - "50000:50000"
复制代码

这其实就是一个普通的PHP开发环境示例:能够看到就phpnginxjenkins三个基本容器,除了jenkins,其余的容器均使用Dockerfile(build配置)来构建。

二、构建脚本:build.sh

因为在docker中实现了nginx配置文件及php源码文件的映射到宿主机,须要经过管理宿主机上文件就能够管理代码的发布和部署了,build.sh就是用来作这件事情的。

固然了,若是须要在部署代码完成以后,作重启、编译等操做,经过sample目录下的钩子就能够实现了。

具体实现能够参考build.sh源码。

4、详细配置

一、开发测试环境域名配置

nginx/conf.d/sample修改测试环境域名,示例中使用的testdomain.com改为本身的测试环境域名便可。

另外,建议把测试域名泛解析到部署这台服务的机器。

二、docker-compose.yml配置说明

docker-compose的配置文件基本不须要修改,只须要关注:nginx是80端口映射到80端口,jenkins是8080端口,而php-fpm的9000端口不对外开放便可。

固然了,若是php环境须要安装依赖,就须要修改./php/Dockerfile。此外,若是须要添加其余的语言环境,就须要添加一个容器的声明。

三、模块配置

1)部署脚本build.sh

业务模块的配置基本是经过部署脚本build.sh来操做的。执行./build.sh提示以下:

Example:
  ./build.sh -u xiongwilee -m php:online,service:online
Usage:
  -u 必填,角色名                       示例:default
  -m 选填,要更新代码的业务模块         示例:php:online,service:online
  -e 选填,更新业务模块对应的环境变量   示例:php:true,service:false
  -d 选填,删除角色                     示例:default
复制代码

2)PHP模块

新增角色实时上是根据php/sample目录建立了一个角色名对应的文件夹。在sample里只有四个文件:

a. 仓储配置
  • .gitaddress:声明当前模块的远程仓储地址
b. 钩子
  • on_add.sh:建立角色时下载PHP模块代码完成以后的回调钩子,用已更新环境变量等文件,执行./build.sh -u {name}会被调用
  • on_upd.sh:某个模块更新完成以后的回调钩子,用以编译、重启服务等操做,执行./build.sh -u {name} -m web:master会被调用
  • on_env.sh:更新环境变量的钩子,执行./build.sh -u {name} -m web:master -e web:true都会被调用。
c. 示例目录app/sample/sample

在sample目录下还有个sample目录,这个是一个php模块示例;新增角色以后访问sample.{name}.testdomain.com就能够来测试是否成功新增。

3)Nginx配置

a. nginx/conf.d目录

和php/sample目录同样,在nginx/conf.d下也有个sample文件,这个也是在新增角色时使用的示例配置文件。注意,新增角色会把sample中的${name}替换成当前角色名。

b. nginx/log目录

nginx/log目录及nginx全部日志文件的宿主机映射目录。

4)Jenkins配置方案

jenkins默认开启8080端口,你能够直接经过http://jenkins.testdomain.com:8080访问jenkins服务。具体初始化过程这里不详述。

a. 安装插件获取当前用户名

在经过Jenkins执行build.sh脚本时,上文提到的角色名怎么获取呢?其实就是jenkins的用户名,你能够经过建立多个jenkins的用户来建立测试环境角色。

参考jenkins插件-Build User Vars Plugin简单说明安装jenkins插件。

安装完成以后就能够经过BUILD_USER环境变量获取当前jenkins的用户名了(固然了,新建jenkins用户的用户名最好是拼音或英文)。

b. Docker镜像中的Jenkins与宿主机通讯

因为jenkins存在Docker镜像中,每次jenkins操做须要执行build.sh都须要使镜像中的jenkins与宿主机通讯。这里使用的方法是,在jenkins的镜像添加到宿主机的信任关系。

而后就能够经过ssh apple@{jenkins内网IP} "sh build.sh"来直接执行宿主机里的脚本了(这里确定还有更优雅的方法)。

c. 添加job

添加一个任务后只须要配置两项:

  1. general:“参数化构建过程”:
    • 选择 "String Parameter",添加"web"、"web-fe"、"service"字段
    • 选择"Boolean Parameter",添加"web_env"、“service_env”字段。
  2. 构建:"Execute Shell":
echo "正在将 web-fe:${web_fe},web:${web},service:${service} 部署到 ${BUILD_USER_ID} 环境"

ssh apple@{jenkins内网IP} "sh ~/docker-compose/build.sh -u ${BUILD_USER_ID} -m web-fe:${web_fe},web:${web},service:${service} -e web:${web_env},service:${service_env}";
复制代码

这样,经过这个任务就能够直接在jenkins中执行宿主机中的build.sh脚本,从而实现新增角色、更新代码的操做了。

最后,若是须要在PHP的服务基础上集成其余语言的服务,好比Nodejs,涉及到的改动有:

  1. 添加Nodejs镜像:docker-compose.yml
  2. 添加部署任务:build.sh
    • 建立及删除角色流程
    • 部署流程
  3. nginx配置文件示例:nginx/conf.d/sample

5、贡献

欢迎提供其余更专业的思路,欢迎提issue、fork;也能够邮件联系:xiongwilee[at]foxmail.com

相关文章
相关标签/搜索