项目地址: https://github.com/xiongwilee/docker-compose-boilerplate
基本特性:
快捷部署多人 nginx+php 的开发测试环境, 也可以扩展构建其他语言;
基于 Docker 和 docker-compose, 不依赖 K8S 等高级编排工具, 成本低廉, 部署简单;
Docker 内置集成 jenkins, 一键添加开发测试角色, 无需额外配置;
支持微服务架构, 适用于小公司 or 敏捷项目团队, 也可以作为 Docker 学习入门的 case;
一, 背景
在角色分工明确的团队里, 什么样的条件才算是最优雅的联调和测试环境? 在大厂里肯定都有很多高级的解决方案, 比如这些:
docker 搭建大规模测试环境的实践 https://yq.aliyun.com/articles/163420 / 测试开发之路 --k8s 下的大规模持续集成与环境治理 https://testerhome.com/topics/15058
DevOps 落地实践: BAT 系列: CICD:iPipe vs CCI https://blog.csdn.net/liumiaocn/article/details/77869653
阿里 DevOps 转型实践 http://www.infoq.com/cn/presentations/ali-devops-transformation-practice
大型团队的合作框架下, 必须依赖更复杂的 DevOps 架构 (参考: DevOps 详解 http://www.infoq.com/cn/articles/detail-analysis-of-devops). 但对于成员不多, 负责的 web 项目工程量也不大的团队, 面临的问题肯定也更单纯:
前后端角色工程解耦, 开发环境分离;
工程师只关注业务逻辑本身, 持续集成;
环境和角色一键创建, 一键更新, 一键销毁, 环境之间不受影响;
即便是只有这些需求, 在以往的 "开发机" 的联调环境里, 一旦需要添加开发或者测试人员, 或者需要更新 nginx 的配置, 再或者需要更新 PHP,Nodejs 的版本...... 对于测试环境的维护来说都是很痛苦的.
二, 快速开始
注意: 当前部署方案仅依赖: Docker,Docker-compose,git
1, 下载代码
$ git clone https://github.com/xiongwilee/docker-compose-boilerplate.git
复制代码
2, 添加测试角色 demo
- $ cd docker-compose
- $ sh build.sh -u demo -m admin:master
复制代码
此时, 在 app / 会创建 demo 目录, 在 nginx/conf.d 会创建 demo.conf 文件.
3, 启动服务
$ docker-compose up -d
复制代码
此时, 再执行 docker-compose ps 会发现创建了三个镜像. 然后, 配置 hosts 使
sample.demo.testdomain.com
指向当前机器, 然后访问 http://sample.demo.testdomain.com 返回 phpinfo() 信息, 说明创建成功.
三, 部署架构说明
TIPS: 这个方案仅适用于小公司 or 敏捷项目团队联调测试环境的部署, 同时也可以作为 Docker 学习入门的 case, 并不适用于有一定规模的生产环境.
在 "开发机" 上仅仅安装 docker,docker-compose,git 之后就能跑起来 Nginx,PHP 的应用, 当然得益于 docker 容器化的思想. 其实这个的实现也仅仅利用了容器化的这个特性, 最终 docker-compose 打包的整个服务会长驻内存, 无需太多的管理成本.
最终的实现还具备两个特点:
基于这个实现的 boilerplate 你可以轻易的迁移到其他项目, 以及其他语言;
每个 sample 管理每个应用的仓储地址, 环境变量配置, 更新代码后的钩子等操作;
其实现原理为: 通过脚本文件, 管理 docker-compose 隐射到宿主机的配置, 源码, 同时将 docker-compose 暴露出来以实现服务的管理. 架构图如下:
1,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 开发环境示例: 可以看到就 php,nginx,jenkins 三个基本容器, 除了 jenkins, 其他的容器均使用 Dockerfile(build 配置) 来构建.
2, 构建脚本: build.sh
由于在 docker 中实现了 nginx 配置文件及 php 源码文件的映射到宿主机, 需要通过管理宿主机上文件就可以管理代码的发布和部署了, build.sh 就是用来做这件事情的.
当然了, 如果需要在部署代码完成之后, 做重启, 编译等操作, 通过 sample 目录下的钩子就可以实现了.
具体实现可以参考 build.sh 源码.
四, 详细配置
1, 开发测试环境域名配置
在
nginx/conf.d/sample
修改测试环境域名, 示例中使用的 testdomain.com 改成自己的测试环境域名即可.
另外, 建议把测试域名泛解析到部署这台服务的机器.
2,docker-compose.yml 配置说明
docker-compose 的配置文件基本不需要修改, 只需要关注: nginx 是 80 端口映射到 80 端口, jenkins 是 8080 端口, 而 php-fpm 的 9000 端口不对外开放即可.
当然了, 如果 php 环境需要安装依赖, 就需要修改./php/Dockerfile. 此外, 如果需要添加其他的语言环境, 就需要添加一个容器的声明.
3, 模块配置
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 简单说明 https://blog.csdn.net/liaojianqiu0115/article/details/78410265 安装 jenkins 插件.
安装完成之后就可以通过 BUILD_USER 环境变量获取当前 jenkins 的用户名了 (当然了, 新建 jenkins 用户的用户名最好是拼音或英文).
b. Docker 镜像中的 Jenkins 与宿主机通信
由于 jenkins 存在 Docker 镜像中, 每次 jenkins 操作需要执行 build.sh 都需要使镜像中的 jenkins 与宿主机通信. 这里使用的方法是, 在 jenkins 的镜像添加到宿主机的信任关系.
然后就可以通过
ssh apple@{jenkins 内网 IP} "sh build.sh"
来直接执行宿主机里的脚本了 (这里肯定还有更优雅的方法).
c. 添加 job
添加一个任务后只需要配置两项:
general:"参数化构建过程":
选择 "String Parameter", 添加 "web","web-fe","service" 字段
选择 "Boolean Parameter", 添加 "web_env","service_env" 字段.
构建:"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, 涉及到的改动有:
添加 Nodejs 镜像: docker-compose.yml
添加部署任务: build.sh
创建及删除角色流程
部署流程
nginx 配置文件示例:
nginx/conf.d/sample
五, 贡献
欢迎提供其他更专业的思路, 欢迎提 issue,fork; 也可以邮件联系: xiongwilee[at] http://foxmail.com .
来源: https://juejin.im/post/5b7952e7e51d4538c17dd75b