使用docker从0到1搭建
安装gitlab
sudo docker run --detach --hostname gitlab.mczaiyun.top --publish 443:443 --publish 80:80 --publish 222:22 --name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab --volume /srv/gitlab/logs:/var/log/gitlab --volume /srv/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce:latest
hostname 域名 或 ip
publish 端口映射
restart 重启方式
gitlab/gitlab-ce:latest 镜像名称
volume 目录挂载
安装gitlab runner
sudo docker run -d --name gitlab-runner --restart always -v /srv/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
docker run --rm -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register --non-interactive --executor "docker" --docker-image alpine:latest --url "http://gitlab.mczaiyun.top/" --registration-token "vtizNrFzQKFacsSMxsJX" --description "first-register-runner" --tag-list "test-cicd1,dockercicd1" --run-untagged="true" --locked="false" --access-level="not_protected"
.gitlab-ci.yml关键词完整解析
使用GitLab自带的流水线,必须要定义流水线的内容,而定义内容的文件默认叫做.gitlab-ci.yml,使用yml的语法进行编写。
目前任务关键词有28个,全局的关键词有10个,两者重叠的有很多。
任务的28个关键词分别是
可用于工作的关键字是:
关键词 | 描述 |
---|---|
after_script |
覆盖作业后执行的一组命令。 |
allow_failure |
允许作业失败。失败的作业不会导致管道失败。 |
artifacts |
成功时附加到作业的文件和目录列表。 |
before_script |
覆盖在作业之前执行的一组命令。 |
cache |
应在后续运行之间缓存的文件列表。 |
coverage |
给定作业的代码覆盖率设置。 |
dast_configuration |
在作业级别使用来自 DAST 配置文件的配置。 |
dependencies |
通过提供要从中获取工件的作业列表来限制将哪些工件传递给特定作业。 |
environment |
作业部署到的环境的名称。 |
except |
控制何时不创建作业。 |
extends |
此作业继承自的配置条目。 |
image |
使用 Docker 镜像。 |
include |
包括外部 YAML 文件。 |
inherit |
选择所有作业继承的全局默认值。 |
interruptible |
定义当新的运行变得多余时是否可以取消作业。 |
needs |
在阶段排序之前执行作业。 |
only |
控制何时创建作业。 |
pages |
上传作业的结果以与 GitLab 页面一起使用。 |
parallel |
应该并行运行多少个作业实例。 |
release |
指示跑步者生成一个释放对象。 |
resource_group |
限制作业并发。 |
retry |
在失败的情况下可以自动重试作业的时间和次数。 |
rules |
用于评估和确定作业的选定属性以及它是否已创建的条件列表。 |
script |
由运行程序执行的 Shell 脚本。 |
secrets |
CI/CD 隐藏作业所需的信息。 |
services |
使用 Docker 服务镜像。 |
stage |
定义作业阶段。 |
tags |
用于选择跑步者的标签列表。 |
timeout |
定义优先于项目范围设置的自定义作业级别超时。 |
trigger |
定义下游管道触发器。 |
variables |
在作业级别定义作业变量。 |
when |
何时运行作业。 |
不可用的工作名称
您不能将这些关键字用作作业名称:
image
services
stages
types
before_script
after_script
variables
cache
include
script, after_script, allow_failure, artifacts, before_script, cache, coverage, dependencies, environment, except, extends, image, include, interruptible, only, pages, parallel, release, resource_group, retry, rules, services, stage, tags, timeout, trigger, variables, when
全局的关键词
image,services,before_script,after_script,tags,cache,artifacts,retry,timeout,interruptible
最常任务中最常用的是这七个
script,artifacts,stage, when,tags,image,cache,
下面我先来详细介绍一下这七个关键词,知道了这个七个关键词,一般的流水线随随便便拿下,
1. script
任务要执行的shell脚本内容,内容会被runner执行,在这里,你不需要使用git clone ....克隆当前的项目,来进行操作,因为在流水线中,每一个的job的执行都会将项目下载,恢复缓存这些流程,不需要你再使用脚本恢复。你只需要在这里写你的项目安装,编译执行,如
npm install 另外值得一提的是,脚本的工作目录就是当前项目的根目录,所有可以就像在本地开发一样。此外script可以是单行或者多行
单行脚本
job:
script: npm install
多行脚本
job:
script:
- npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
- npm install --registry=http://registry.npm.taobao.org
script是一个job的必填内容,不可或缺。一个job最少有二个属性,一个是job name
任务名称, 一个就是script
。
stage(阶段)
stage 是阶段的意思,用于归档一部分的job,按照定义的stage顺序来执行。默认的stage有build,test,deploy, 此外还有两个特殊的.pre 和 .post, job执行的顺序不是按照编写的顺序,大体上是按照stage定义的顺序来执行的,注意是大体,也有例外的情况。
如果文件中stages
没有定义.gitlab-ci.yml
,那么默认的流水线阶段是:
stages项目的顺序定义了作业的执行顺序:
- 同一阶段的作业并行运行。
- 下一阶段的作业在上一阶段的作业成功完成后运行。
例如:
stages:
- build
- test
- deploy
- 中的所有作业
build
并行执行。 - 如果所有作业都
build
成功,则test
作业并行执行。 - 如果所有作业都
test
成功,则deploy
作业并行执行。 - 如果所有作业都
deploy
成功,则管道标记为passed
。
如果任何作业失败,管道将被标记为failed
并且后续阶段的作业不会启动。当前阶段的作业不会停止并继续运行。
如果作业未指定stage
,则为该作业分配test
阶段。
.pre =>`build=>test=>deploy=>.post
//最简单,如果不指定stages,默认为test阶段
job1:
script:
-echo ‘my prejob‘
//stages划分阶段执行,先执行job1=>job2=>job3
stages:
- stage1
- stage2
- stage3
job1:
stage:stage1
script:
- echo ‘my stage1‘
job2:
stage:stage2
script:
- echo ‘my stage2‘
job3:
stage:stage3
script:
- echo ‘my stage3‘
//=====================
stages:
- linecode
- install
- build
- deploy
- clean
job1:
stage:build
script:
- echo ‘my buildjob‘
job1:
stage:test
script:
- echo ‘my testjob‘
由于build在test之前所有会指向job1这个任务,后指向job0任务
retry
test:
script:rspec
retry:2: //运行失败之后,最多再尝试2次
max:2
when:runner_system_failure //限定触发失败时机
image
指定一个基础Docker镜像作为基础运行环境,经常用到的镜像有node nginx docker
job:
image: node:latest
script: npm install
在上面这个任务中,如果不指定image: node:latest 执行下面的npm install时会报错,找不到npm的命令。image的作用就是给当前任务或者当前流水线设置一个基础环境,有可能是nodejs,也有可能是java, go, php,可以设置当前流水线的,也可以设置当前任务的。
artifacts
翻译出来这个单词就是制品,一个成品,作用是将流水线过程中的一些文件,文件夹,打包压缩,提供一个外链供人下载,另外还能在后续的job中缓存。
比如我们构建一个前端项目后将dist目录做成一个压缩包,
build:
script:
- npm run build
artifacts:
paths:
- dist/
在这个任务后面运行的任务会自动恢复这个制品,意味着你不用再执行npm run build来获取编译后的dist文件了,在安卓,ios打包的时候,非常有用,因为流水线最终输出的就是一个可下载,可安装的应用。paths 是用来指定将那些文件,目录放入制品中,也可以使用exclude关键词,将那些目录,文件排除,支持正则表达式。
此外还有以下几个属性
- paths 文件路径
- exclude 排除的文件
- name 制品名称
- expose_as 在UI页面导出的名称
- untracked 布尔类型,是否将git忽略的文件加到制品中
- when on_success;on_failure;always 何时上传制品
- expire_in 过期时间默认30天
- reports 收集测试报告
- build:
script:
- npm run build
artifacts:
paths:
- dist/
exclude:
- binaries/**/*.o
expose_as: ‘artifact 1‘
name: "$CI_COMMIT_REF_NAME"
untracked: false
expire_in: 2 hrs 20 min
when: on_failure
tags
tags 关键词是用于指定Runner,tags的取值范围是在该项目可见的runner tags中,可以在Setting =>CI/CD => Runner 中查看的到。要知道,改属性可以设置全局,不设置则默认使用公有Runner去执行流水线。每个任务可以指定一个Runner,可以指定多个标签,但runner却只能一个。以一个为准。tags是在我们注册Runner是配置的,后续也可以更改。
install:
tags:
- hello-vue
- docker
script:
- npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/
- npm install --registry=http://registry.npm.taobao.org
cache
缓存是将当前工作环境目录中的一些文件,一些文件夹存储起来,用于在各个任务初始化的时候恢复。避免多个下载同样的包,能够大大优化流水线效率。在前端项目中,我们经常把node_modules缓存起来,这样一条流水线都可以使用这些下载好的包。在java项目中经常把maven下载的包缓存起来。以备后用
cache下的参数有
-
paths 当前工作环境下的目录
-
key 存储的key,key不变不会重新生成缓存,
-
:key:\?prefix
使用一些文件制作成文件hash值,当做key的一部分 -
untracked 是否缓存git忽略的文件
-
when 定义何时存储缓存 on_success;on_failure;always
-
policy 缓存是否要在job完成后重新上传
缓存可以设置流水线全局,也可以在job中设置
cache:
key: hello-vue-cache
paths:
- node_modules
cache:
key:
files:
- Gemfile.lock
- package.json
paths:
- vendor/ruby
- node_modules
when
when关键字是实现在发生故障或尽管发生故障时仍能运行的作业。比如你要在任务失败后需要触发一个job,
或者你需要手动执行任务,或者当你一个任务执行成功后,执行另一个任务.
- on_success 所有任务执行成功后
- on_failure 当至少一个任务失败后
- always 执行作业,而不考虑作业在早期阶段的状态。
- manual 手动执行任务
- delayed 延迟执行任务
- never在rules中不排除执行的任务在workflow:rules不允许的流水线
only/except
only/except 是规定当前job的可见状态,一个项目有很多分支,tag,我们的流水线,为了对特定的分支,特定的tag执行不同的job,这里就要使用only和except
在任务上加上这一段代码,就表明当前任务只有在master分支可以运行
only:
- master
也可以根据当前的代码变动是合并,还是推送,还是使用API来触发的。
如果一个任务没有only属性,那默认就是only: [‘branches‘, ‘tags‘]
操作分支或者tags都会触发流水线。
before_script
before_script 关键词是用于在每个任务之前执行的脚本,但是会在artifacts恢复之后执行。你可以这样定义一个全局的before_script,
default:
before_script:
- echo "Execute this script in all jobs that don‘t already have a before_script section."
也可以在一个任务中中单独定义
job:
before_script:
- echo "Execute this script instead of the global before_script."
script:
- echo "This script executes after the job‘s `before_script`"
任务中的before_script会覆盖全局的before_script
after_script
after_script与before_script类似,用于定义多行脚本,会在任务执行完成后执行,即使任务失败也会被执行。如果任务被取消或者超时,after_script就不会被执行了,目前官方正在计划这个特性。
可以定义全局的,也可以定义局部的
default:
after_script:
- echo "Execute this script in all jobs that don‘t already have an after_script section."
job1:
script:
- echo "This script executes first. When it completes, the global after_script executes."
job:
script:
- echo "This script executes first. When it completes, the job‘s `after_script` executes."
after_script:
- echo "Execute this script instead of the global after_script."
dependencies
dependencies关键词是定义特定的job运行规则。默认artifacts是从当前阶段产生,在后续的阶段都会被下载,但我们可以使用dependencies关键词来控制artifacts从哪里下载,
这里有一个例子,
build:osx:
stage: build
script: make build:osx
artifacts:
paths:
- binaries/
build:linux:
stage: build
script: make build:linux
artifacts:
paths:
- binaries/
test:osx:
stage: test
script: make test:osx
dependencies:
- build:osx
test:linux:
stage: test
script: make test:linux
dependencies:
- build:linux
deploy:
stage: deploy
script: make deploy
根据这个例子我们不难看出,
任务test:osx 依赖build:osx
任务test:linux 依赖 build:linux
这样配置以后 任务test:linux 就不用等任务build:osx 执行完成在执行了,只需要等待任务build:linux完成
很好地利用了依赖关系来优化流水线的速率,前四个任务都执行完成后,才会执行最后一个部署的任务。
environment
environment是用于定义环境变量,可以是用k-v的方式定义
如
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production
需要注意的是这里定义的环境变量是不能在script值使用的。
这个关键词可以和review和merge搭配。
extends
这个关键词可以使一个任务继承另一个任务。
如下案例
.tests:
script: rake test
stage: test
only:
refs:
- branches
rspec:
extends: .tests
script: rake rspec
only:
variables:
- $RSPEC
任务rspec 继承了.tests任务,在流水线中.tests是一个隐藏的任务,在流水线中,以英文远点开头的任务名,都是隐藏的任务。不会被执行。 被rspec继承后,相同的key会以rspec为准,rspec没有的,而.tests有的,则合并到rspec中,
合并后的结果是
rspec:
script: rake rspec
stage: test
only:
refs:
- branches
variables:
- $RSPEC
使用这一个手段,可以写一个模板,只要稍微改改就能后使用。非常适合大批量编写流水线。
include
使用include可以导入一个或多个额外的yaml文件到你的CICD配置里,这一你就可以将一个很长的流水线,分隔出来。使用include来引入。
也可以将几个流水线中相同的配置,提取出来,公用。引入的文件扩展名 必须是.yaml或者.yml两种,其他的不行。
include 关键词下,有四个可选性,
local, 引入一个当前项目的文件
file, 引入一个不同项目的文件
remote, 引入一个公网文件,
template, 引入一个由GitLab提供的模板
下面是几个例子
include:
- local: ‘/templates/.gitlab-ci-template.yml‘
include:
- project: ‘my-group/my-project‘
file: ‘/templates/.gitlab-ci-template.yml‘
include:
- local: ‘/templates/.gitlab-ci-template.yml‘
include:
- project: ‘my-group/my-project‘
ref: master
file: ‘/templates/.gitlab-ci-template.yml‘
- project: ‘my-group/my-project‘
ref: v1.0.0
file: ‘/templates/.gitlab-ci-template.yml‘
- project: ‘my-group/my-project‘
ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA
file: ‘/templates/.gitlab-ci-template.yml‘
include:
- remote: ‘https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml‘
trigger
trigger 是应对那些更加复杂的CICD流程,如多流水线,父子流水线
使用它可以定义一个下游的流水线,配置了trigger的任务是不能跑脚本的,就是说不能定义script, before_script, 和 after_script.
项目这个是一个多项目流水线
rspec:
stage: test
script: bundle exec rspec
staging:
stage: deploy
trigger: my/deployment
流水线执行完test任务后就会去执行my/deployment项目的流水线
配置下游流水线式也可以执行分支
rspec:
stage: test
script: bundle exec rspec
staging:
stage: deploy
trigger:
project: my/deployment
branch: stablez
rules
rules是用于规定任务的执行规则,使用一个表达式,来规范那些任务执行,那些任务不执行.还可以在任务成功,或者失败后,触发另一个任务。
如下面这个例子
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: ‘$CI_COMMIT_BRANCH == "master"‘
when: delayed
start_in: ‘3 hours‘
allow_failure: true
如果当前的分支是master分支则任务执行就延迟3个小时,并且允许失败。
rules的下面有是哪个可选属性
if 使用if表达式 添加或移除一个任务, 类似 only:variables.
changes 根据某些个文件是否改变来追加或移除一些任务。类似 only:changes.
exists 根据是否存在特定文件来追加或移除一些任务
if中可以使用CICD的所有预设变量,分支,来源,合并请求,commit,push web,schedule等。可以针对不用的情景配置不用的规则。
在看下这个例子
job:
script: echo "Hello, Rules!"
rules:
- if: ‘$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"‘
when: manual
allow_failure: true
解释起来并不复杂,一个判断语句,二句赋值语句。即如果当前分支是master,在任务的执行方式改为手动,并且运行失败。