首页 > 云计算 > > docker+webhook自动化部署实践
自动化部署是一门最大限度简化不必要工作的工程艺术,通过自动化部署,可以实现互联网业务的产品直达DevOps一站式服务,极大的解放了生产力。
本文将使用docker+webhook以及shell实现一个小型的单机自动化部署系统。
一切技术都离不开业务,先看下我们的系统架构:

1、api(由koa编写的RESTful API)
2、core(Web前端)
由于前端为SPA(Single Page Application,单页面应用),所以还需要一个项目专门用来存储core经过打包之后的文件,这些文件最终将会同步到服务器上,这个项目叫:core-dist
此外,我们还需要一个负责处理自动化的脚本项目,我们叫它:deploy
最后,我们还需要负责同步开发机和服务器代码的webhook,我们就叫它:webhook
将这些项目依次在Github 上创建,最终结果如下:

目前的部署具体需求是:
现在我们开始吧。
.
├── README.md
├── api
│ ├── Dockerfile
│ └── deploy.sh
├── deploy.sh
├── domain.sh
├── domain_api_deploy.sh
├── domain_pix_deploy.sh
├── domain_tpls_deploy.sh
├── mongodb
│ └── deploy.sh
└── core
├── Dockerfile
└── deploy.sh可以看到deploy项目下有三个文件夹;api、core和mongodb,这三个文件夹代表了三个核心业务docker,每个文件夹下,先从最简单的core开始吧,它放置的是打包之后的web前端静态资源。
core
Dockerfile
FROM nginx
MAINTAINER ivy 'xieyang@dodora.cn'
RUN rm -rf /usr/share/nginx/html
ENTRYPOINT cd /usr/share/nginx/html && nginx && /bin/bash
这个Dockerfile非常简单,就是一个最基础的nginx容器。
deploy.sh
这个文件用来停止、删除、构建和启动容器。
docker stop core && docker rm core
docker build -t core .
docker run -itd -p 7777:80 -v /mnt/pix/core-dist:/usr/share/nginx/html -w /usr/share/nginx/html --name="core" core
可以看到我们挂载了宿主机的/mnt/pix/core-dist的目录到容器内的nginx目录内。/mnt/pix/core-dist内是打包好的Web前端静态资源,我们使用docker部署遵循一个原则:
docker内不存储任何数据,所有数据都在宿主机上,这些数据包括程序代码和用户数据。
待会我们会说到怎么往宿主机上同步代码。
接下来是api和数据库docker,这两个需要放在一起说。
先看api:
Dockerfile
FROM node:7.10
MAINTAINER ivy 'xieyang@dodora.cn'
RUN apt-get update
RUN apt-get install zip -y
#use cnpm
RUN npm install -g cnpm --registry=https://registry.npm.taobao.org
RUN cnpm install -g supervisor
# 修改时区
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENTRYPOINT cd /var/www/api && supervisor index.js && /bin/bash
我们用到了zip这个命令和supervisor来运行node程序(没用pm2是因为觉得暂时没必要),其它都是基本的node 7.0容器信息。
deploy.sh
docker stop api && docker rm api
docker build -t api .
docker run -itd -p 7776:3000 -v /mnt/pix/api:/var/www/api/ -v /mnt/pix/templates:/var/www/api/templates -w /var/www/api --name="api" --link mongodb:mongo api
可以看到我们将宿主机上的/mnt/pix/api(api源代码)暴露至了容器中的/var/www/api文件夹,还用到了--link命令,link命令可以连接我们的mongodb。
mongodb
mongodb不需要重新构建镜像,直接使用官方的mongodb镜像即可。
deploy.sh
docker rmi mongodb
docker run -v /mnt/pix/mongodb/db:/data/db -d --name="mongodb" mongo:3.2
我们挂载了一个目录,将容器内的数据目录挂载到了宿主机上,保证了数据的安全性(docker本身是无状态的)。
至此,我们就完成了docker容器的自动化构建,第一个需求完成了。
运行顺序中,必须先启动mongodb再启动api,core可以随意。
初始化服务器环境非常容易,只要写一个shell脚本即可,以下是这个项目的初始化脚本(处于项目安全考虑,敏感内容已***代替):
mkdir /mnt/pix
mkdir /mnt/pix/mongodb
mkdir /mnt/pix/mongodb/db
#templates
git clone *** /mnt/pix/templates
#pix-dist
git clone *** /mnt/pix/pix-dist
#pix-api
git clone *** /mnt/pix/api
cd /mnt/pix/api && npm install
#docker images
sh ./mongodb/deploy.sh
sh ./api/deploy.sh
sh ./pix/deploy.sh
#webhook
git clone *** /mnt/pix/webhook
cd /mnt/pix/webhook && npm install
pm2 start /mnt/pix/webhook/index.js --name pix_webhook
#配置域名
sh ./domain.sh
还隐掉了很多软件包的安装,这些视项目决定,就没必要写出来了。
至此,我们完成了服务器环境的初始化,注意上面的代码中有一个webhook,这个是用来做自动化同步代码的。
webhook是github提供的功能,这个功能可以在github服务器接收到客户端发来的push消息后,再向服务器发送一个api,这个api由用户自定义,代码同步也在这个api里做。
本项目的webhook由nodejs写成,非常短,代码如下:
var http = require('http');
var exec = require("shelljs").exec;
const PORT = 6474;
console.log('listening port at: ' + PORT);
const cmds = {
'/api/build': 'cd /mnt/pix/api && git pull',
'/pixweb': 'cd /mnt/pix/pix-dist && git pull',
'/webhook': 'cd /mnt/pix/webhook && git pull && pm2 restart pix_webhook',
'/deploy': 'cd ~/pix/deploy && git pull',
'/templates': 'cd /mnt/pix/templates && git pull'
}
var deployServer = http.createServer(function(request, response) {
var inCMDs = false,
cmd = '';
for(var key in cmds) {
if(key == request.url) {
inCMDs = true;
cmd = cmds[key];
break;
}
}
if(inCMDs) {
exec(cmd, function(err, out, code) {
if (err instanceof Error) {
response.writeHead(500);
response.end('Server Internal Error.');
throw err
}
process.stderr.write(err.toString());
process.stdout.write(out.toString());
response.writeHead(200);
response.end('Deploy Done.');
})
主要看第8-14行即可,键是url,后面的值是要执行的shell命令。
比如这个项目运行在localhost:6474端口,那么假如我要将api的代码同步至服务器,我只要发送一个post请求到http://localhost:6474/api/dev即可,注意在实际使用中,localhost应使用外网ip,因为这个请求是github发送的。
再回过头来看我们部署webhook的shell代码:
#webhook
git clone *** /mnt/pix/webhook
cd /mnt/pix/webhook && npm install
pm2 start /mnt/pix/webhook/index.js --name pix_webhook使用了pm2启动webhook,至此,还没完,还差最后一步,我们还未将url配置到github上。

打开任意的项目,按照如图所示配置即可。
配置完成后,我们推送到github上的每一行代码,都将自动同步到服务器上。
至此,我们完成了第二个需求。
现在只剩第三个需求,即nginx域名需求。
这个就非常简单了,随便举个例子即可:
sudo tee /etc/nginx/conf.d/api.****.cn.conf <<- 'EOF'
upstream nodejs__upstream_pxi_core {
server 127...1:7476;
keepalive 64;
}
server {
listen 80;
server_name www.api.****.cn api.****.cn;
#access_log /var/log/nginx/moiveme.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://nodejs__upstream_pxi_core;
}
}
EOF通过upstream代理到对应的docker端口即可。
还有最后一项工作要做,记得吗?前端的部署是分开的,源代码同步到github上,打包之后的代码同步到服务器上。
npm run build
cp favicon.icon dist
zip dist.zip -r dist
rm -rf /var/www/pix/pix-dist/*
mv dist.zip /var/www/pix/pix-dist
cd /var/www/pix/pix-dist && git pull && unzip dist.zip && cd dist && mv * ../ && cd ../ && rm -rf dist.zip && rm -rf dist && git add . && git commit -a -m 'constrution' && git push -u origin master单独部署也很简单,思路就是写一个shell将打包之后的代码放置到core-dist项目下然后push到github中,上面的代码就干的这事,体力活,没啥技术含量。
至此,我们完成了所有需求,一套简单的自动化部署系统也完成了,接下来,尽情的写代码吧。
自动化部署真的是一门艺术。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3121442/ ,如需转载,请注明出处,否则将追究法律责任。