├── README.md ├── daocloud-banner.jpg ├── daocloud.md └── gitlab.md /README.md: -------------------------------------------------------------------------------- 1 | # docker-ci 系列 2 | 基于docker 搭配各种 CI 系统 做一个简单够用的持续集成环境 3 | 4 | 1. [gitlab-docker-ci](https://github.com/Ye-Ting/docker-ci/blob/master/gitlab.md) 5 | 1. [daocloud-docker-ci](https://github.com/Ye-Ting/docker-ci/blob/master/daocloud.md) 6 | -------------------------------------------------------------------------------- /daocloud-banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ye-Ting/docker-ci/7fde56537db57b093a20e35841be155f1c8696cc/daocloud-banner.jpg -------------------------------------------------------------------------------- /daocloud.md: -------------------------------------------------------------------------------- 1 | # DaoCloud-Docker-CI 2 | 基于Docker 与 DaoCloud 建立简单够用的持续集成环境 3 | 4 | ![DaoCloud-docker-ci](/daocloud-banner.jpg "DaoCloud-Docker") 5 | 6 | 本次持续集成环境主要构成 7 | 8 | 1. 代码版本库 coding.net 9 | 2. CI服务 DaoCloud 10 | 3. CI运行器 DaoCloud 11 | 12 | 搭建过程中的主要步骤 13 | 14 | 1. 在coding.net上添加代码库 15 | 1. 申请DaoCloud自有主机服务(目前在内测中需要申请) 16 | 1. 安装docker 17 | 1. 搭建基础 docker image 18 | 1. 把代码库添加到DaoCloud生成项目 19 | 1. 编写daocloud.yml 20 | 1. 发布镜像 21 | 1. 完成一个简单够用的持续集成环境 22 | 23 | ## 在coding.net上添加代码库 24 | 这步不是重点,我只是随便选了一个daocloud支持的代码源。 25 | 26 | 目前(2015-06-14)DaoCloud支持的代码源是: 27 | 28 | 1. Github 29 | 1. Bitbucker 30 | 1. Coding 31 | 1. GitCafe 32 | 33 | 期间有个小插曲刚注册coding在激活用户的时候出现一个Bug。 34 | Bug真的是无处不在。 35 | 36 | ## 申请DaoCloud 自有主机 服务 37 | DaoCloud自有主机官方介绍 38 | [DaoCloud邀请您体验全新混合式容器主机管理服务](http://blog.daocloud.io/daocloud_sr_alpha/) 39 | 40 | 完成申请之后自由主机申请之后 41 | [安装主机监控程序](https://dashboard.daocloud.io/runtimes/new) 42 | 43 | 应该是需要登陆以及具有自有主机服务的权限才能进入上面链接。我直接把命令复制下来 44 | ``` 45 | curl -sSL https://get.daocloud.io/docker | sh // 安装docker 46 | 47 | curl -sSL https://get.daocloud.io/daomonit/install.sh | sh -s XXXXXXXX //这是自有主机的标识,系统随机生成 48 | 49 | sudo service docker restart 50 | ``` 51 | 完成上面步骤之后我们就能在Daocloud/我的主机 看到我们已经链接上的主机信息 52 | 包含`主机ip`、`CPU使用率`、`内存使用率`、`磁盘使用率`、`主机上的容器` 53 | 54 | `主机上的容器`这个功能真的是太吊了,至于多么吊,大家自己试试看就知道了。所有信息一目了然 有木有! 55 | 56 | ## 搭建基础docker image 57 | DaoCloud 提供了一些基础镜像用于搭建测试环境,貌似他们的提供的环境不是我想要的额,所以很多时候就要我们自己去DIY这个基础的运行镜像。自己DIY还是有蛮多好处的。 58 | 59 | 1. 每次下的库就那么几个测试用的第三方库就固定那么几个,每次都要下,先不说其他,下载库的时间要等吧?做个基础镜像,也帮DaoCloud省省带宽,重点是我们自己的程序在构建的时间跑的快。不然每次都要等个10+分钟,对于我这种性子急得人真是要命。 60 | 2. 自己做的镜像里面有啥玩意自己都知道,能hold住。有坑自己也能填上。 61 | 3. 酷,自己搭的镜像逼格比用别人搭的高。 62 | 63 | 由于我的代码环境是PHP,我这里就拿PHP来举例子,来构建PHP运行及测试环境。 64 | 65 | No Code No BB,直接上 Dockerfile: 66 | ``` 67 | FROM php:5.6-apache 68 | MAINTAINER YeTing 69 | 70 | #Download Require 71 | RUN apt-get update && apt-get install -y libmcrypt-dev libz-dev git wget \ 72 | && docker-php-ext-install mcrypt mbstring zip \ 73 | && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 74 | 75 | ENV PATH=$PATH:~/.composer/vendor/bin 76 | 77 | RUN composer global require "phpunit/phpunit=~4.0" "phpspec/phpspec=~2.1" "laravel/envoy=~1.0" && a2enmod rewrite 78 | ``` 79 | 这个dockerfile很简单 80 | 81 | 武林秘籍第一式:找一个靠谱的镜像 82 | ``` 83 | FROM php:5.6-apache 84 | MAINTAINER YeTing 85 | ``` 86 | https://registry.hub.docker.com/ 上面有很多官方的镜像,我自己DIY的镜像就是基于官方`php:5.6-apache`镜像来做的。 87 | 个人镜像多多少少会有一些坑等着我们去踏,我们还是踏踏实实的根据我们的需求自己写一个Dockerfile。不过别人写的都可以借(chao)鉴(xi)。 88 | 89 | 武林秘籍第二式:精确定位 90 | ``` 91 | RUN apt-get update && apt-get install -y libmcrypt-dev libz-dev git wget \ 92 | && docker-php-ext-install mcrypt mbstring zip \ 93 | && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 94 | ``` 95 | 要啥就下啥,知道我们每次下载的东西是拿来干什么的,不然为什么要下呢。 96 | `docker-php-ext-install`是官方镜像中提供的一个配置PHP环境的方法,所以文档我们还是要多看看的。不然好东西都发现不了。`composer`是一个PHP的包管理工具,类似于node与npm的关系。 97 | 98 | 武林秘籍第三式:欲练此功,必先利其器 99 | ``` 100 | ENV PATH=$PATH:~/.composer/vendor/bin 101 | 102 | RUN composer global require "phpunit/phpunit=~4.0" "phpspec/phpspec=~2.1" "laravel/envoy=~1.0" && a2enmod rewrite 103 | ``` 104 | 前人的经验真是数不胜数,前人创造的工具我们也好好好利用。`phpunit` `phpspec` 是PHP上的测试工具。`envoy`一个简易的部署工具,我们在后面的部署会用到。`a2enmod rewrite`apache开启url重写模块。 105 | 106 | 基础镜像终于好了,我们的测试,部署可都是要靠它了。 107 | 108 | ## 新建DaoCloud项目 109 | 起项目名,绑定项目代码源,一个项目就建好了。还是很简单的。 110 | 111 | 首次生成项目的时候会默认拉取`master`分支,构建一个`master-init`的镜像,(当然项目中是要包含Dockerfile),只要构建成功,我们就能把这个镜像部署到我们自己的主机上。这个部署可比我上一篇 [基于docker 与 gitlab CI 做一个简单够用的持续集成环境](https://github.com/Ye-Ting/docker-ci/blob/master/gitlab.md)中的部署,简单好多,轻轻一点就行。构建是在DaoCloud服务器上做的,据说他们还备好了梯子给我们拉第三方库的时候好翻墙。 112 | 113 | 记得在部署的时候选择自己关联到DaoCloud的主机,不然默认会部署在DaoCloud提供的主机上。DaoCloud提供的主机也还不错,就是访问速度慢了点,胜在不用钱的。不过我们都自己搭了主机,当然还是部署到我们自己的主机上是最妥的。 114 | 115 | 我们可以开启`自动发布`功能,每当有镜像构建成功,DaoCloud就会帮我们自动发布。 116 | 117 | ## 编写daocloud.yml 118 | 在DaoCloud代码测试需要用到DaoCloud。所以我们要先来看看官方的介绍。 119 | [daocloud.yml的格式](http://help.daocloud.io/v1.0/docs/daocloud-yml) 120 | 和 [官方的例子](https://github.com/DaoCloud/daocloud-doc/blob/master/DaoCloudCI.md) 121 | 122 | 看完了之后,发现还是格式蛮简单的,例子好长,都快看不下去了。就一个重点 123 | 124 | ### How it works 125 | 1. 设置环境变量 126 | 1. 执行install脚本 127 | 1. 克隆源代码,切换对应的commit 128 | 1. 执行before_script脚本 129 | 1. 执行script脚本 130 | 131 | 做好前期准备,我们就来写自己项目的daocloud.yml 132 | ``` 133 | image: yeting/laravel-prebuild-docker // 我们的基础镜像 134 | 135 | env: 136 | - MYENV = "hello" // 纯粹为了测试代码执行 137 | 138 | install: 139 | - echo $MYENV 140 | 141 | before_script: //执行测试前的准备 142 | - composer config -g github-oauth.github.com XXXX 143 | // 个人的github token 这个有一个github上面的坑,限制了非认证用户下载dist包的次数,60次/小时。这个限制很容易就超了,超了之后下的库超慢 144 | - composer install 145 | // composer依赖包安装 composer是php上的包管理工具类似于npm与node的关系 146 | 147 | script: // 执行测试 148 | - phpunit //php单元测试 149 | 150 | ``` 151 | 152 | 写了daocloud.yml,DaoCloud会在你每次的代码push的时候,进行测试。 153 | 154 | 不过有点略坑的是,每次测试通过的时候,他不会帮你自动build,需要自己build。 155 | 就这一点,联系DaoCloud工作人员。他们说,并不是每一次代码的push都需要build成镜像的,如果需要build,需要在该代码版本上打一个tag,这样DaoCloud才会把代码build成镜像。这样也能解决我们自动build的需求,也还行。 156 | 157 | 部署的时候就点击打包好的镜像,发布到我们自己的主机上,就可以了,这点真的很赞,好方便。DaoCloud还帮你存了好多个镜像,供你随时切换着版本部署,想想他们也不容易啊。 158 | 159 | ##总结 160 | 一个简单够用的持续集成环境,就这样完成了,真不敢相信,是不是很简单?太酷了。 161 | 162 | DaoCloud真的的是一个贴心的开发者伙伴。希望他们在未来的路上走的更远。 163 | 164 | Docker是一项好技术,但是我们要以正式的姿势去使用它。 165 | 166 | 要做一个能hold住技术的开发者,而不是盲目跟随潮流最求新技术的人。 167 | 168 | 工具能提高人的效率,而产品的还坏最终还是在于人。 169 | 170 | 这是我个人的第一个系列的技术博客,希望能与更多的人进行交流。 171 | 172 | 本篇博客为个人原创,转载请联系 me@yeting.info 173 | -------------------------------------------------------------------------------- /gitlab.md: -------------------------------------------------------------------------------- 1 | # gitlab-docker-ci 2 | 基于docker 与 gitlab CI 做一个简单够用的持续集成环境 3 | 4 | 本次持续集成环境主要构成 5 | 6 | 1. 代码版本库 Gitlab 7 | 2. CI服务 Gitlab CI 8 | 3. CI运行器 GitLab Runner-docker (项目地址 https://gitlab.com/gitlab-org/gitlab-ci-multi-runner) 9 | 10 | 搭建过程中的主要步骤 11 | 12 | 1. 在Gitlab上添加代码库 13 | 1. 把代码库添加到Gitlab CI中 14 | 1. 安装docker 15 | 1. 搭建基础 docker image 16 | 1. 设置Gitlab Runner-docker 17 | 1. 编写测试脚本 18 | 1. 编写构建脚本 19 | 1. 优化过程 20 | 1. 完成一个简单够用的持续集成环境 21 | 22 | 前面3个步骤较简单,并且网上教程较多,这里不做赘述。 23 | 24 | ## 搭建基础docker image 25 | Gitlab Runner-docker 默认镜像是Ruby2.1,但是Ruby这门语言我不会,并且我的代码环境不是Ruby所以很多时候就要我们自己去DIY这个基础的运行镜像。 26 | 27 | 由于我的代码环境是PHP,我这里就拿PHP来举例子,来构建PHP运行及测试环境。 28 | 29 | No Code No BB,直接上 Dockerfile: 30 | ``` 31 | FROM php:5.6-apache 32 | MAINTAINER YeTing 33 | 34 | #Download Require 35 | RUN apt-get update && apt-get install -y libmcrypt-dev libz-dev git wget \ 36 | && docker-php-ext-install mcrypt mbstring zip \ 37 | && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 38 | 39 | ENV PATH=$PATH:~/.composer/vendor/bin 40 | 41 | RUN composer global require "phpunit/phpunit=~4.0" "phpspec/phpspec=~2.1" "laravel/envoy=~1.0" && a2enmod rewrite 42 | ``` 43 | 这个dockerfile很简单 44 | 45 | 武林秘籍第一式:找一个靠谱的镜像 46 | ``` 47 | FROM php:5.6-apache 48 | MAINTAINER YeTing 49 | ``` 50 | https://registry.hub.docker.com/ 上面有很多官方的镜像,我自己DIY的镜像就是基于官方`php:5.6-apache`镜像来做的。 51 | 个人镜像多多少少会有一些坑等着我们去踏,我们还是踏踏实实的根据我们的需求自己写一个Dockerfile。不过别人写的都可以借(chao)鉴(xi)。 52 | 53 | 武林秘籍第二式:精确定位 54 | ``` 55 | RUN apt-get update && apt-get install -y libmcrypt-dev libz-dev git wget \ 56 | && docker-php-ext-install mcrypt mbstring zip \ 57 | && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 58 | ``` 59 | 要啥就下啥,知道我们每次下载的东西是拿来干什么的,不然为什么要下呢。 60 | `docker-php-ext-install`是官方镜像中提供的一个配置PHP环境的方法,所以文档我们还是要多看看的。不然好东西都发现不了。`composer`是一个PHP的包管理工具,类似于node与npm的关系。 61 | 62 | 武林秘籍第三式:欲练此功,必先利其器 63 | ``` 64 | ENV PATH=$PATH:~/.composer/vendor/bin 65 | 66 | RUN composer global require "phpunit/phpunit=~4.0" "phpspec/phpspec=~2.1" "laravel/envoy=~1.0" && a2enmod rewrite 67 | ``` 68 | 前人的经验真是数不胜数,前人创造的工具我们也好好好利用。`phpunit` `phpspec` 是PHP上的测试工具。`envoy`一个简易的部署工具,我们在后面的部署会用到。`a2enmod rewrite`apache开启url重写模块。 69 | 70 | ##设置Gitlab Runner-docker 71 | Good job,基础镜像我们已经完成了。我们进行下一步。 72 | 来来,我们的参考资料 https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/install/docker.md 73 | 上面给了我们两种存储数据的方式一个是直接存储在本地,另一个是创建docker data container 。(好像第二种比较高端。貌似字数也能多一点。我们就用第二种吧。) 74 | ``` 75 | docker run -d --name multi-runner-data -v /data busybox:latest /bin/true 76 | 77 | docker run -d --name multi-runner --restart always \ 78 | --volumes-from multi-runner-data \ 79 | ayufan/gitlab-ci-multi-runner:latest 80 | ``` 81 | windows上的同学们,我们要注意`\`,把代码改成同一行运行。 82 | 83 | 因为我们在这个容器里面还需要运行docker,把命令修改一下 84 | ``` 85 | docker run -d --name multi-runner --restart always \ 86 | -v /var/run/docker.sock:/var/run/docker.sock \ 87 | --volumes-from multi-runner-data \ 88 | ayufan/gitlab-ci-multi-runner:latest 89 | ``` 90 | 这样我们就能在docker里面运行docker 91 | 92 | ``` 93 | docker exec -it multi-runner gitlab-ci-multi-runner register 94 | 95 | Please enter the gitlab-ci coordinator URL (e.g. http://gitlab-ci.org:3000/ ) 96 | https://ci.gitlab.org/ 97 | 这里我用官网地址,也可以是自己搭的gitlab-ci地址 98 | Please enter the gitlab-ci token for this runner 99 | 这里填gitlab-ci的token 100 | Please enter the gitlab-ci description for this runner 101 | 你的runner的名字 102 | INFO[0034] fcf5c619 Registering runner... succeeded 103 | Please enter the executor: shell, docker, docker-ssh, ssh? 104 | docker 105 | Please enter the Docker image (eg. ruby:2.1): 106 | yeting/laravel-prebuild-docker 107 | 这个是我自己搭的镜像名字,上传到了docker hub上了, 108 | 109 | 还有一些其他配置 一律回车 过! 110 | 111 | INFO[0037] Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 112 | 看到这句话就成功了 113 | ``` 114 | 在Github CI 的项目里面的runners选项,看到了一个新的runner,就是那个了。在这个页面可以进行激活、停止等操作 115 | 116 | ##编写测试脚本 117 | 在Github CI 的项目里面的jobs选项,我们看到 Test 和 Deploy。 118 | 119 | Test 的脚本执行`success`之后 就会执行 Deploy的。 不然是不会执行的。 120 | 121 | 里面还有一些功能大家自行摸索。 122 | ``` 123 | ls -la 124 | 125 | composer config -g github-oauth.github.com XXX // 个人的github token 这个有一个github上面的坑,限制了非认证用户下载dist包的次数,60次/小时。这个限制很容易就超了。属于优化部分 126 | composer config cache-dir /cache/composer // 修改composer 缓存目录 属于优化部分 127 | 128 | composer install // 依赖包安装 129 | phpunit // 单元测试 130 | ``` 131 | 132 | ##编写构建脚本 133 | 测试完成之后我们就可以部署了。 134 | ``` 135 | ls -al 136 | ls -al ~/.ssh 137 | envoy run deploy 138 | ``` 139 | 别看这脚本这么这么简单,其实还是有很多事情要做的。 140 | 141 | 我们在本地需要构建一个 Deploy的镜像,也是为了保密,咱总不能什么东西都往网上丢吧。 142 | 目录结构 143 | ``` 144 | - Dockerfile 145 | - Envoy.blade.php 146 | - ssh 147 | -- config 148 | -- id_rsa //这个不用说了吧,一个密钥 149 | ``` 150 | ssh/config 里面的内容 151 | ``` 152 | ost * 153 | StrictHostKeyChecking no 154 | ``` 155 | Envoy.blade.php 具体语法 http://laravel.com/docs/5.0/envoy 156 | ``` 157 | @servers(['web' => 'ubuntu@xxx.xxx.xxx.xxx']) 158 | 159 | @task('deploy') 160 | cd xx 161 | git pull 162 | docker-compose build 163 | docker-compose up 164 | @endtask 165 | ``` 166 | Dockerfile 167 | ``` 168 | FROM yeting/laravel-prebuild-docker:latest 169 | MAINTAINER YeTing 170 | Copy ./ssh /root/.ssh // 覆盖该docker 容器的ssh 171 | ``` 172 | 这样的我们的构建脚本就完成了80%了,还有什么? 173 | 我们还需要在我们的代码库中添加docker-composer.yml 174 | 175 | docker-composer 具体文档 https://docs.docker.com/compose/ 176 | docker-composer 成功之后 177 | 178 | 修改Gitlab Runner-docker 运行镜像为我们最新构建的镜像,我这里起名为`yeting/laravel-deploy-docker` 179 | 180 | 好了 这样我们部署脚本就完成了。 181 | 182 | ## 优化过程 183 | 前面已经完整的介绍了如何搭建一个简单够用的持续集成环境,但是在运行过程中,我们还会碰到一些问题,比如过 第三方包的依赖管理,每次跑环境的时候都需要从外网下载,在我大中(tian)国(chao)的网速下真心无奈。所以我们需要对中间的过程做一些优化。 184 | 185 | 在我们的测试脚本中,有这么一段命令 186 | ``` 187 | composer config cache-dir /cache/composer 188 | ``` 189 | 他的意思就是将composer的缓存目录更换到 `/cache/composer`目录下。 190 | 为什么要换到`/cache`目录? 191 | 192 | 我们执行 193 | ``` 194 | docker exec -it multi-runner bash 195 | ``` 196 | 输出 `/data/config.toml`内容 197 | ``` 198 | [[runners]] 199 | name = "test" 200 | url = "https://ci.gitlab.com/" 201 | token = "xxxxx" 202 | executor = "docker" 203 | [runners.docker] 204 | image = "laravel-deploy-docker" 205 | privileged = false 206 | volumes = ["/cache"] 207 | ``` 208 | 每一个runnner都会默认的配置一个 `/cache` 挂载,也就是说我们存在/cache目录下的文件会持续更新。 209 | 我们利用这一特性,把我们地三方包下载时候的cache放在`/cache/composer`目录。run个几次之后,我们跑测试的时间从 `10+分钟` 变成 `10+秒` 超级炫酷,有木有! 210 | 211 | 当然不仅仅只有composer可以这么做,其他有相似特性的第三方包管理工具都可以这么做。 212 | 213 | 可能你还会问,跑测试脚本的时候可以这么做,但是我在部署的时候呢?就不应该这么做了。 214 | 215 | 我这里有一种,简单粗暴。等我们第一次部署完成之后,我们可以将运行中代码的第三方包依赖目录(我这里是 `vendor`目录 )全部复制出来,放在我们的本机的源码目录下,每次在docker build的时候,能直接将第三方依赖包复制到运行目录,这样我们在构建过程中就不需要再下载了。 216 | 217 | 当然这种方法还有一点缺点的,在项目的依赖包发生变化的时候,每次执行 composer install 的时候还是会需要去拉取变化的包。出现这样的情况我们就需要重复上面的操作。(这种方式真的是 简单并且粗暴 一点都不符合我那追求优雅的心 不过暂时我就探究到这种程度,如果有哪位大神有更加好的方式,请告诉我,我十分乐意改进) 218 | 219 | ##总结 220 | 一个简单够用的持续集成环境,就这样完成了,真不敢相信,是不是很简单?太酷了。 221 | Gitlab真的的是一个贴心的开发者伙伴。Docker是一项好技术,但是我们要以正式的姿势去使用它。 222 | 223 | 要做一个能hold住技术的开发者,而不是盲目跟随潮流最求新技术的人。 224 | 225 | 工具能提高人的效率,而产品的还坏最终还是在于人。 226 | 227 | 这是我个人的第一篇技术博客,希望能与更多的人进行交流。 228 | 229 | 本篇博客为个人原创,转载请联系 me@yeting.info 230 | --------------------------------------------------------------------------------