最近把公司的 beta
环境作了容器化,目前达到的效果是代码提交到 gitlab
,触发 webhook
将代码部署到测试服务器,而后就能够根据先后端不一样的分支组合的域名来访问,从而省去了每次先后端代码都合并到 master
分支才能测试的环节。php
nginx-proxy 是一个 Docker 容器, 是实现本文解决方案的神器,只需简单的配置,即可实现为多个容器路由的功能。前端
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
假设有域名 foo.bar, 使用泛域名解析将 *.foo.bar解析到当前服务器便可。node
假设有一个运行 web 服务的容器,只须要在启动的时候加上 -e VIRTUAL_HOST=web.foo.bar
,就能够实现对该容器的访问了。nginx
docker run -e VIRTUAL_HOST=web.foo.bar ...
注意:若是使用 docker-compose 管理多个容器的时候,docker-compose 会为这些容器建立一个网桥,这样会使得后来手动建立的容器无法被路由,因此这里不建议使用 docker-compose 来管理。git
ui-for-docker 是一个基于 docker remote api 实现的 web 管理界面,虽然界面不怎么样,可是基本上经常使用的功能已经实现了,前端使用 angular 实现,能够根据本身的需求做修改。github
clone 代码web
npm install && bower installdocker
grunt run (更多操做可参看 gruntFile.js 文件)npm
使用 Gitlab 提供的 webhook 功能完成自动部署代码,期间遇到一些问题:ubuntu
经过 webhook 的请求执行用户是 www-data,若是要在 hook 脚本中进行文件的写入操做是总会遇到权限问题,最暴力的办法就是给目录所有 777 或者在 Dockerfile 中将 www-data 用户加入 sudo 组,而且无需输入密码。
echo " data-www ALL=NOPASSWD: ALL" >> /etc/sudoers
固然,正式的环境中须要对权限作严格控制,作到最小权限原则。
Gitlab 触发 hook 请求以后会一直等待服务器返回 HTTP 200
的状态码,若是没收到,会重复触发 hook,若是 hook 脚本执行时间过长会致使 HTTP 请求超时,或者一次代码提交触发屡次部署请求,因此最后我选择用异步的方式,hook 脚本只须要接受上线指令,写入队列,上线过程交给另一个脚原本完成。
为了减小环境配置的麻烦,可使用文件队列,php 可参考 Filefifo.php。
可将队列目录挂载到 webhook 容器上,便可实现容器内部写入,主机读取队列(可以使用supervisor 来管理该进程),完成代码部署的过程。
使用 supervisor 管理上线脚本进程,须要把日志回显到 web 界面,首先在 supervisor 的配置文件中配置好日志路径,而后建立一个 websocket 容器,将日志目录挂载到容器中,再tail 读取日志文件,实时显示在 web 界面。
可参考 websocket。
下游容器将先后端环境作了分离,下降耦合度,在使用过程当中会减小一些麻烦。分离时会遇到浏览器同源策略的问题,可将先后端容器作互联,而后后端容器反向代理到前端容器。
在部署代码的时候可根据不一样的分支将代码部署到不一样的目录,而后建立容器的时候把不一样的分支目录挂载到不一样的容器中,便可实现开发分支的随意搭配。
对于一些服务,有时候只须要一个很是简单的 web 容器就能够,好比上面的前端容器,可是若是使用 ubuntu + nginx 的配置的时候会发现镜像要几百兆,很不划算,因此考虑精简镜像。
受这篇文章的启发,打算本身用 go 实现一个简单的 web 服务器,这样 build 好的镜像基本上只有十几兆,可是因没有作相关的测试,因此还不敢放在线上。
最后选择了使用 alpine + nginx 的策略,build 以后的镜像以后几十兆,已经减小了不少冗余的东西,具体可参考simple-nginx。
通过无数次踩坑和不停的折腾,终于能够勉强使用了,固然还存在一些瑕疵,以后会慢慢修复。
感谢期间帮助过个人每一位同事。