我们通常将项目托管在 GitHub、GitLab 或码云上,每次本地更新代码后,可能还需要进入项目部署目录 pull 一次,比较麻烦。利用 WebHook 可以很好的实现自动化部署。本地 push 代码,代码更新到托管服务器,触发 WebHook 钩子,部署服务器接受到 POST 请求,执行部署更新操作。
本教程以将托管在码云上的 Laravel 项目部署到 CentOS 服务器上为例进行说明。
主要步骤如下:
在代码托管平台(如码云)上添加部署公钥。
添加 WebHook。
部署服务器添加部署操作。
克隆代码并测试。
部署公钥只允许以只读的方式访问项目,主要用于项目在生产服务器的部署,免去 HTTP 方式每次操作都需要输入密码和普通 SSH 方式担心不小心修改项目代码的麻烦。
注意,因为 Nginx 默认是以 www 身份来运行的,所以我们要以 www 用户来生成部署公钥,不然会出现权限问题。
登录部署服务器,生成部署 SSH 公钥:
sudo -u www ssh-keygen -t rsa -C "user@example.com"
# Generating public/private rsa key pair.
# 三次回车即可
查看公钥,并添加到码云:
cat /home/www/.ssh/id_rsa.pub
# ssh-rsa AAA...
在码云上为项目添加一个 WebHook,有三个参数:
URL(*):接收 WebHook 数据的 HTTP 地址。码云将发送 POST 请求到这个地址。
密码:为了保证安全以及识别数据来源,建议设置一个密码。
钩子:用户在码云上可触发的 WebHook,支持添加多个钩子。
作为演示,地址填写:https://domain.com/deploy
,密码 domain_deploy_secret
,钩子选择 Push
,具体可以实际情况自己设置。
以 Laravel 为例,我们定义一个路由,来执行部署命令:
routes/web.php
Route::post('deploy', 'PagesController@deploy');
app/Http/Controllers/PagesController.php
public function deploy()
{
$path = base_path();
$password = 'domain_deploy_secret';
$json = json_decode(file_get_contents('php://input'), true);
if (empty($json['password']) || $json['password'] != $password) {
return 'invalid request';
}
shell_exec("cd $path && /usr/local/git/bin/git pull origin master");
shell_exec("cd $path && /usr/local/bin/composer install --no-dev");
shell_exec("cd $path && /usr/bin/php artisan migrate");
return 'success';
}
由于 Laravel 中间件默认会验证 CSRF Token,所以需要在 VerifyCsrfToken
中间件中排除 deploy
路由。
app/Http/Middleware/VerifyCsrfToken.php
class VerifyCsrfToken extends Middle
{
protected $except = [
'deploy',
];
}
第一次还是需要以 SSH 方式手动克隆项目。
git config --global user.name "username"
git config --global user.email "user@example.com"
chattr -i /home/wwwroot/domain.com/.user.ini
rm -rf /home/wwwroot/domain.com
sudo -u www /usr/local/git/bin/git clone git@gitee.com:username/rep.git domain.com # 确定要有权限
cd domain.com
sudo -u www /usr/local/bin/composer install --no-dev
sudo -u www cp .env.example .env
sudo -u www php artisan key:generate