更新推荐
使用Gitlab Runner 部署Laravel 项目
此文档基于现有项目运行实践整理,其中包含了许多Gitlab、CI/CD相关概念,阅读需要有一定的Gitlab、Docker、CI/CD基础知识。
- 此项目能做什么
- Git-Flow/Github-Flow/Gitlab-Flow工作流
- 快速运行Gitlab
- 持续集成/持续交互
- Gitlab-Runner自动构建与部署的执行
- CI/CD运行流程
- CI/CD分布式
- 分享一些关于团队Git版本控制使用心得。
- 提供一份Docker版本的Gtilab私有化仓库应用实现,让你在开发团队内部快速构建一套Git托管仓库系统。
- 提供一份Gitlab Docker容器编排实现参考,分离Gitlab/Redis/PostgreSQL/Gitlab-CI和运行时数据。
- 提供一份Gitlab Runner Docker版本实现,在Runner容器内部增加了对PHP的支持,利用Laravel Envoy实现远程操作多台主机,实现分布式自动构建与交付。
- 加深对软件从编码 =》 构建 =》 测试 =》 部署的整个生命周期的认知,
- 为Web/Web API类型互联网产品自动化提供参考,适合中小型创业研发团队快速迭代版本。
Git团队开发中,大家都在向仓库中提交功能代码,时间久了,分支与版本就逐渐增多而变得复杂,因此,一个合理的版本管理流程在项目初期就非常重要。
使用Git,多数时候推荐流行的git-flow工作流程 git-flow 备忘清单。通常,develop分支作为测试版本使用,所有开发者都能够向该分支合并代码,以保证代码经过评审和功能验证。master分支作为线上版本使用,只有仓库管理员才能向该分支合并代码,以确保线上版本稳定。
- feature branches 功能特性分支,基于develop分支开发,在功能开发完成后,代码会被合并到develop分支,此分支也自动删除。
- develop 测试分支,一般基于该分支构建应用的测试环境。
- release branches 发布分支。新功能开发完成,经过了代码评审和功能验证后,仓库管理员使用
git flow release start 1.0.0
命令方式合并develop分支到master分支。使用该命令,需要确保master分支与develop分支基础版本一致。 - hotfixes 修复分支,一般而言,在线上环境出现问题,需要紧急修复时,需创建hotfix修复补丁分支,它基于master分支开发,补丁修复代码会被合并至master与develop分支。
- master 生产分支,一般基于该分支中构建应用的生产环境。
在单人Git开发场景下,此流程足以满足需求,但是在多人的开发团队中,有时候稍显"无力",而Gitlab/Github推荐使用PR/MR的方式,开发者需要主动发起分支合并申请,在得到确认后,分支开发才算完成。
开发者基于主干分支先创建新的功能性分支,在功能开发完成后,需要作Merge Request申请,也即是主动请求合并功能分支代码到主干分支。仓库管理员会评审每一次MR,只有评审通过,新功能才被提交上线。
Gitlab提供社区与企业版本,官网提供多种Gitlab安装方式。此项目是基于Docker版本的Gitlab实现,开发者无需更多关心Gitlab安装过程,Docker镜像已做好了环境和依赖。
该项目基于Docker GitLab 镜像构建,它将Gitlab/PostgreSQL/Redis容器拆分,分离了运行时数据。同时,提供一套容器编排配置参考,支持Docker Compose快速构建与维护。
确保你的主机已经安装好了Docker与Docke-Compose,按照下面的方式快速运行Gitlab。
-
克隆仓库
$ git clone https://github.com/bravist/gitlab-docker $ cd ~/gitlab-docker
-
配置环境变量,推荐使用默认配置
$ cp .env.example .env
-
使用
docker-compose
构建镜像和启动容器$ docker-compose build && docker-compose up -d
-
确认容器构建成功,Gitlab Web控制台访问:http://localhost:10080/,如果出现502错误,请稍后再次访问,容器构建Gitlab需要等待依赖安装完成。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8827363f45d8 sameersbn/gitlab:10.3.3 "/sbin/entrypoint.sh…" 4 seconds ago Up 4 seconds 443/tcp, 0.0.0.0:10022->22/tcp, 0.0.0.0:10080->80/tcp gitlabdocker_gitlab_1 db0dd3b3d23f bravist/gitlab-ci-php-envoy:1.0 "/usr/bin/dumb-init …" 7 seconds ago Up 6 seconds gitlab-ci-php-envoy-runner f598844c561c sameersbn/redis:latest "/sbin/entrypoint.sh…" 7 seconds ago Up 6 seconds 6379/tcp gitlab-redis 73d93b7cd110 sameersbn/postgresql:9.6-2 "/sbin/entrypoint.sh" 7 seconds ago Up 5 seconds 0.0.0.0:5432->5432/tcp gitlab-postgresql
项目内置了Gitlab Runner镜像,默认会启动一台Gitlab Runner容器,让你在本地可以快速搭建CI/CD服务。
CI/CD 的全称是 Continuous Integration & Deployment (持续集成/部署),是 extreme programming (极限编程) 的一部分。我们常用 CI 来做一些自动化工作,这种自动化工作会运行在一台集中的机器上,比如程序的打包,单元测试,部署等。 维基百科 - 持续集成
Gitlab 从 8.* 版本后支持CI/CD,要使用CI/CD,先理解一些概念
Pipeline
一次Pipeline就是一次完整的构建任务,里面可以包含多个阶段(stages)。
Stage
Stages表示任务构建的阶段。一次Pipeline中允许定义多个 Stages,这些 Stages 会有以下特点:
- 所有 Stages 会按照顺序运行,即当一个 Stage 完成后,下一个 Stage 才会开始
- 只有当所有 Stages 完成后,该构建任务 (Pipeline) 才会成功
- 如果任何一个 Stage 失败,那么后面的 Stages 不会执行,该构建任务 (Pipeline) 失败
Job
Jobs 表示构建工作,表示某个 Stage 里面执行的工作。 我们可以在 Stages 里面定义多个 Jobs,这些 Jobs 会有以下特点:
- 相同Stage中的Jobs会并行执行
- 相同Stage中的Jobs都执行成功时,该 Stage 才会成功
- 如果任何一个Job失败,那么该 Stage 失败,即该构建任务 (Pipeline) 失败
我把Pipelines理解为流水线,流水线包含有多个阶段(stages),每个阶段包含有一个或多个工序(jobs),比如先购料、组装、测试、包装再上线销售,每一次Push或者MR都要经过流水线之后才可以合格出厂。
Gilab中,仓库的.gitlab.ci.yml文件负责定义项目具体工作任务和流水线,Gitlab Runner基于配置好的流水线逐步执行任务,直到任务完成,如果中途错误,它会立即停止后续的任务。如果项目使用Gitlab CI,需要提前添加该文件。
stages:
- pull_code_test
- pull_code_production
- install_deps
- test
- build
- deploy_test
- deploy_production
variables:
PHP_FPM_CONTAINER: lnmp-php-fpm
WORK_DIR: /usr/share/nginx/html/
PROJECT: laravel-demo
GIT_DIR: /mnt/lnmp-docker
# 拉取代码
pull_code_test:
stage: pull_code_test
only:
- develop
script:
- cd ${GIT_DIR}/${PROJECT}
- git pull origin develop
pull_code_production:
stage: pull_code_production
only:
- master
script:
- cd ${GIT_DIR}/${PROJECT}
- git pull origin master
# 安装依赖
install_deps:
stage: install_deps
script:
- docker exec -w ${WORK_DIR}/${PROJECT} ${PHP_FPM_CONTAINER} composer install
build:
stage: build
script:
# Run migrations
- docker exec -w ${WORK_DIR}/${PROJECT} ${PHP_FPM_CONTAINER} php artisan migrate
# Cache clearing
- docker exec -w ${WORK_DIR}/${PROJECT} ${PHP_FPM_CONTAINER} php artisan cache:clear
# Create a cache file for faster configuration loading
- docker exec -w ${WORK_DIR}/${PROJECT} ${PHP_FPM_CONTAINER} php artisan config:cache
# Create a route cache file for faster route registration
- docker exec -w ${WORK_DIR}/${PROJECT} ${PHP_FPM_CONTAINER} php artisan route:clear
deploy_test:
stage: deploy_test
script:
- cd ${GIT_DIR}
- docker-compose down && docker-compose build && docker-compose up -d
deploy_production:
stage: deploy_production
script:
- cd ${GIT_DIR}
- docker-compose restart
GitLab Runner 是一个开源项目, 它用来运行你定制的任务(jobs)并把结果返回给 GitLab。 GitLab Runner 配合GitLab CI(GitLab 内置的持续集成服务) 协调完成任务。 GitLab Runner
简单的说,Gitlab Runner是独立运行配置好了Gitlab CI/CD项目的机器,它负责Gitlab项目的自动构建和部署的运行。
Gitlab Runner安装有多种方式,具体可以参考官方文档,这里推荐使用基于Docker的版本 bravist/gitlab-ci-php-envoy,镜像源码已同步在此项目中,上面的章节也能看到运行的容器。
Gitlab Runner安装运行之后,需要注册到Gitlab项目中去,才能使用其“功效”。
登录Gitlab控制台,选择一个Gitlab仓库,进入 Settings =》CI / CD =》Runners settings =》Expand,获取Runners相关参数。
$ docker exec -it gitlab-ci-php-envoy-runner gitlab-ci-multi-runner register
Running in system-mode.
#输入CI URL
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://gitlab.weipeiapp.com:10080/
#输入CI Token
Please enter the gitlab-ci token for this runner:
eU9zcqjReSozw6a1RLL8
#输入描述信息
Please enter the gitlab-ci description for this runner:
[f6c7de92c743]: Gitlab CI usage
#输入标签信息
Please enter the gitlab-ci tags for this runner (comma separated):
v1.0
#是否运行未标记的版本
Whether to run untagged builds [true/false]:
[false]: true
#是否运行当前项目
Whether to lock the Runner to current project [true/false]:
[true]: true
Registering runner... succeeded runner=eU9zcqjR
#输入Runner的类型
Please enter the executor: shell, virtualbox, docker-ssh+machine, kubernetes, docker, docker-ssh, parallels, ssh, docker+machine:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
注册成功后,页面会多出一个正在运行的Runner绿色标志。
如果你了解bravist/lnmp-docker,对于下面的图不会陌生,主要提供了一套Web应用自动构建与交付流程架构。
通常情况下Gitlab Runner与Gitlab无需运行在同一台服务器,他们之间通信基于授信TOKEN,整个运行流程是:
- 基于Gitlab Flow 完成功能开发
- 提交Merge Request,等待功能发布申请
- 评审Merge Request,允许合并分支请求
- 触发Gitlab Runner运行
- 执行项目 .gitlab.ci.yml 配置好的流水线任务
- 完成CI/CD流水线工作,工作结束
以一个前端项目为例,构建过程会做以下任务
- 拉取Git代码
- 安装前端依赖
- 打包、编译
本项目Gitlab Runner默认采用Shell方式执行部署任务,也即是Runner使用SSH登录到应用主机。你可以在Runner容器中生成新的ssh秘钥对(或者使用能够登录到应用主机的其他ssh秘钥对),确保能成功SSH到应用主机。
进入到Runner容器
docker exec -it gitlab-ci-php-envoy-runner sh
使用ssh登录远程应用主机
ssh root@47.*.*.69
如果成功登录,表示自动部署链接工作没有问题。如果你的应用部署了多台服务器,推荐使用Larave Envoy部署任务。Laravel Envoy 基于PHP实现,提供了灵活的配置方便在应用主机构建任务。 bravist/gitlab-ci-php-envoy Runner基于gitlab/gitlab-runner镜像,又增加了对PHP的支持,完全支持Laravel Envoy部署。
要使用Laravel Envoy,需要在仓库中增加Envoy.blade.php文件,定义好所有主机需要做的事情。
@servers(['sandbox' => 'root@47.*.*.45', 'production' => 'root@47.*.*.69'])
@story('sandbox_deploy', ['on' => ['sandbox']])
git
logistics-debt
@endstory
@story('production_deploy', ['on' => ['production']])
git
logistics-debt
@endstory
@task('git')
cd /mnt/lnmp-docker/www/{{ $project }}/
git config --global user.email "chenghuiyong1987@gmail.com"
git config --global user.name "Gitlab Runner"
git pull origin {{ $branch }}
@endtask
@task('logistics-debt')
cd /mnt/lnmp-docker/www/{{ $project }}/logistics-debt
cnpm install
npm run build
@endtask
同时,在仓库的.gitlab-ci.yml文件中定义使用Envoy执行构建任务。
stages:
- sandbox
- production
variables:
ENVOY: /root/.composer/vendor/bin/envoy
sandbox:
stage: sandbox
script:
- cd $CI_PROJECT_DIR
- $ENVOY run sandbox_deploy --branch=develop --project=$CI_PROJECT_NAME
only:
- develop
production:
stage: production
script:
- cd $CI_PROJECT_DIR
- $ENVOY run production_deploy --branch=master --project=$CI_PROJECT_NAME
only:
- master