利用Git hooks实现自动化部署

 2016-12-19 21:25:07     Git   1485


导读: 通过Git hooks,可以实现服务的自动化部署,提高效率。

假设一个公司有员工A和员工B,正式环境在外网服务器上,Gitlab和测试环境在内网服务器。我们要实现员工用Git提交代码后,代码自动提交到内网和外网服务器,同时,完成相关服务器上代码的自动更新和服务的自动启动。

结构图


我的结构图大体如下:

结构图

实际情况,是不允许个人直接将代码提交到线上环境,并触发相关服务的。可能只允许提交到内网服务器,然后经过内网验证成功后,由运维人员再将代码提交到线上服务器。

由于是个人项目,为了开发和测试方便,才这样设计。

步骤说明


以下为简单实现的步骤,在生产环境使用的话,会比这个更复杂:

  • 1、首先,需要在服务器A创建一个bare仓库,作为一个共享仓库
  • 2、然后,在本地克隆Git服务器的仓库,修改Git配置文件,使其支持push到多仓库
  • 3、编写hooks脚本,实现自动更新项目和重启服务
  • 4、在本地提交项目,验证测试

操作


安装Git

在内外网服务器和本地安装Git。我们假设内网的Gitlab已经安装完成。

groupadd git

useradd -G git git

apt-get install git

禁止shell登录

对于线上服务器,出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:

git:x:1003:1003:,,,:/home/git:

改为:

git:x:1003:1003:,,,:/home/git:/usr/bin/git-shell

注意:

  • 1003为账号的id,系统会按照账号添加的顺序递增,所以,此处应该为各自账号的id

免密钥登录

打通本地机器与服务器的免密钥登录。此处内容省略。

创建bare仓库

git init不一样的是,git init --bare 并不存储实际代码,仓库文件夹不会看到任何项目代码。

在外网服务器A上创建bare。

cd /home/git
mkdir repository

cd repository

git init --bare blog.git

chown -R git:git /home/git/repository

#不对0x80以上的字符进行quote,解决中文显示为编码的问题
git config --global core.quotepath false

本地克隆

进入到本地工作空间,克隆项目。

git clone git@wangrun.love:/home/git/repository/blog.git

wangrun.love为我自己为服务器配置的host。

构建项目目录结构,提交项目。

git add .
git commit -m 'crate project'
git remote add blog git@wangrun.love:/home/git/repository/blog.git
git push blog master

修改配置文件

进入项目.git目录下,边界config文件。

[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        symlinks = false
        ignorecase = true
[remote "origin"]
        url = git@wangrun.love:/home/git/repository/blog.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
[remote "blog"]
        url = git@wangrun.love:/home/git/repository/blog.git
        url = git@gitlab.ssports.com:/home/git/repository/blog.git#此处为手动增加内容,实现向多个远程仓库提交代码
        fetch = +refs/heads/*:refs/remotes/blog/*

push到多个仓库。

git add .
git commit -m 'update code'
git push blog master

服务器克隆

我们假设服务器A和服务器B都部署了blog项目。

我的项目是用OpenResty开发的,安装路径为/usr/local/openresty,Nginx的部署路径为/opt/apps/nginx-app/blog/。详细安装见OpenResty安装

首先,我们先在服务器A克隆一下项目blog

cd /opt/apps/nginx-app/

git clone /home/git/repository/blog.git

编写hook脚本

进入/home/git/repository/blog.git/hooks目录下,将post-receive.sample文件重命名为post-receive

编辑post-receive,实现服务器A自动更新项目和重启Nginx。

#!/bin/sh

echo "`date +"%Y-%m-%d %H:%M:%S"` Info: start sync blog"
unset $(git rev-parse --local-env-vars)

cd /opt/apps/nginx-app/blog
git pull

echo "`date +"%Y-%m-%d %H:%M:%S"` Info:end sync blog"
sudo /usr/local/openresty/nginx/sbin/nginx -s reload

#sh +x ./scripts/sync_code.sh >> /tmp/hook_test.log

exit 0

注意post-receive文件的权限,要赋予可执行权限。

chmod +x post-receive

集群同步


当代码提交到外网服务器A时,要求同时同步到服务器B。有多种方式实现:

  • 1、在post-receive中,通过ssh免密钥登录到服务器B,进入项目路径,执行pull操作
  • 2、在post-receive中,通过scp命令拷贝到服务器B,但是无法重启服务
  • 3、在服务器B部署一个监听服务,通过post-receive向监听发送命令,触发服务器B的执行脚本

测试


在本地修改项目文件,并提交,登录网站,看内容是否更新。

在本地Git提交代码时,post-receive的输出信息也会显示出现在控制台,通过输出信息也可以是否报错。


参考