Docker&Gitlab-CI Deploy

Docker & Gitlab CI

1. Docker basic command list
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ docker pull (image) (tag)            //从官方源拉取镜像
$ docker images = docker image ls //显示镜像列表
$ docker ps //显示docker进程
$ docker container ls
$ docker start CONTAINER_ID
$ docker system df //显示内存信息
$ docker stop CONTAINER_NAME //关闭container
$ docker restart CONTAINER_NAME //重启container
$ docker run img:tag
OPTION:
-a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
-d: 后台运行容器,并返回容器ID;
-rm: 退出时自动清理容器内部的文件系统
-i: 以交互模式运行容器,通常与 -t 同时使用;
-P: 随机端口映射,容器内部端口随机映射到主机的端口
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
--name="nginx-lb": 为容器指定一个名称;
--dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
--dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
-h "mars": 指定容器的hostname;
-e username="ritchie": 设置环境变量;
--env-file=[]: 从指定文件读入环境变量;
--cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
-m :设置容器使用内存最大值;
--net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container:四种类型;
--link=[]: 添加链接到另一个容器;
--expose=[]: 开放一个端口或一组端口;
--volume , -v: 绑定一个卷
2. Deploy GitLab Runner
  • Install

使用本地卷安装

1
2
3
4
$ docker run  -d --name gitlab-runner --restart always \ 
-v /srv/gitlab-runer/config:/etc/gitlab-runer \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest

使用Docker卷安装

1
2
3
4
5
6
>$ docker volume create gitlab-runner-config

>$ docker run -d --name gitlab-runner --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v gitlab-runner-config:/etc/gitlab-runner \
gitlab/gitlab-runner:latest
  • Regist GitLab Runer

upload successful

Get Token Here

1
2
3
4
5
6
7
8
9
10
11
docker run --rm -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register \
--non-interactive \
--executor "docker" \
--docker-image alpine:latest \
--url "$gitlab address" \
--registration-token "$TOKEN" \
--description "first-register-runner" \
--tag-list "test-cicd, dockercicd" \ (runner 标签)
--run-untagged="true" \
--locked="false" \
--access-level="not_protected"
3. runner 配置

配置文件
/srv/gitlab-runner/config/config.toml


全局的部分
concurrent 限制能够同时run多个job 0为不限制
log_level 可选项 debug, info, warn, error, fatal, panic
check_interval 检查周期 检查新的job 单位秒 默认三秒

官方文档 https://docs.gitlab.com/runner/configuration/advanced-configuration.html

Setting Description
name Runner 的名字 描述
url GitLab 地址
token The Runner’s special token (not to be confused with the registration token)
tls-ca-file File containing the certificates to verify the peer when using HTTPS
tls-cert-file File containing the certificate to authenticate with the peer when using HTTPS
tls-key-file File containing the private key to authenticate with the peer when using HTTPS
limit Limit how many jobs can be handled concurrently by this token. 0 (default) simply means don’t limit
executor Select how a project should be built, see next section
shell Name of shell to generate the script. Default value is platform dependent.
builds_dir Absolute path to a directory where builds will be stored in context of selected executor (Locally, Docker, SSH)
cache_dir Absolute path to a directory where build caches will be stored in context of selected executor (locally, Docker, SSH). If the docker executor is used, this directory needs to be included in its volumes parameter.
environment Append or overwrite environment variables
request_concurrency Limit number of concurrent requests for new jobs from GitLab (default 1)
output_limit Set maximum build log size in kilobytes, by default set to 4096 (4MB)
pre_clone_script Commands to be executed on the Runner before cloning the Git repository. this can be used to adjust the Git client configuration first, for example. To insert multiple commands, use a (triple-quoted) multi-line string or “\n” character.
pre_build_script Commands to be executed on the Runner after cloning the Git repository, but before executing the build. To insert multiple commands, use a (triple-quoted) multi-line string or “\n” character.
post_build_script Commands to be executed on the Runner just after executing the build, but before executing after_script. To insert multiple commands, use a (triple-quoted) multi-line string or “\n” character.
clone_url Overwrite the URL for the GitLab instance. Used if the Runner can’t connect to GitLab on the URL GitLab exposes itself.
debug_trace_disabled Disables the CI_DEBUG_TRACE feature. When set to true, then debug log (trace) will remain disabled even if CI_DEBUG_TRACE will be set to true by the user.
referees Extra job monitoring workers that pass their results as job artifacts to GitLab
4. yml file
  • 基本关键词

    任务关键词:
    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
任务要执行的shell脚本内容,内容会被runner执行,在这里,你不需要使用git clone ….克隆当前的项目,来进行操作,因为在流水线中,每一个的job的执行都会将项目下载,恢复缓存这些流程,不需要你再使用脚本恢复。你只需要在这里写你的项目安装,编译执行,如
npm install 另外值得一提的是,脚本的工作目录就是当前项目的根目录,所有可以就像在本地开发一样。此外script可以是单行或者多行

单行脚本

1
script: npm install

多行脚本

1
2
3
4
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。

image
指定一个基础Docker镜像作为基础运行环境,经常用到的镜像有node nginx docker

1
2
3
job:
image: node:latest
script: npm install

在上面这个任务中,如果不指定image: node:latest 执行下面的npm install时会报错,找不到npm的命令。
image的作用就是给当前任务或者当前流水线设置一个基础环境,有可能是nodejs,也有可能是java, go, php,
可以设置当前流水线的,也可以设置当前任务的。

artifacts
翻译出来这个单词就是制品,一个成品,作用是将流水线过程中的一些文件,文件夹,打包压缩,提供一个外链供人下载,另外还能在后续的job中缓存。
比如我们构建一个前端项目后将dist目录做成一个压缩包,

1
2
3
4
5
6
build:
script:
- npm run build
artifacts:
paths:
- dist/

在这个任务后面运行的任务会自动恢复这个制品,意味着你不用再执行`npm run build来获取编译后的dist文件了,
在安卓,ios打包的时候,非常有用,因为流水线最终输出的就是一个可下载,可安装的应用。
paths 是用来指定将那些文件,目录放入制品中,
也可以使用exclude关键词,将那些目录,文件排除,支持正则表达式。
此外还有以下几个属性

  • paths 文件路径
  • exclude 排除的文件
  • name artifac名称
  • expose_as 在UI页面导出的名称
  • untracked 布尔类型,是否将git忽略的文件加到artifact中
  • when on_success;on_failure;always 何时上传artifact
  • expire_in 过期时间默认30天
  • reports 收集测试报告
1
2
3
4
5
6
7
8
9
10
11
12
13
14

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是配置的,后续也可以更改。

1
2
3
4
5
6
7
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不变不会重新生成缓存,
  • 🔑prefix 使用一些文件制作成文件hash值,当做key的一部分,
  • untracked 是否缓存git忽略的文件
  • when 定义何时存储缓存 on_success;on_failure;always
  • policy 缓存是否要在job完成后重新上传
    缓存可以设置流水线全局,也可以在job中设置
1
2
3
4
cache:
key: hello-vue-cache
paths:
- node_modules
1
2
3
4
5
6
7
8
cache:
key:
files:
- Gemfile.lock
- package.json
paths:
- vendor/ruby
- node_modules

stage

stage 是阶段的意思,用于归档一部分的job,按照定义的stage顺序来执行。
默认的stage有build,test,deploy, 此外还有两个特殊的.pre 和 .post
job执行的顺序不是按照编写的顺序,大体上是按照stage定义的顺序来执行的,注意是大体,也有例外的情况。

1
2
3
4
5
6
7
8
9
10
11
12
stages:
- build
- test
- deploy

job 0:
stage: test
script: echo 'tets'

job 1:
stage: build
script: echo 'build'

由于build在test之前所有会指向job1这个任务,后指向job0任务

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分支可以运行

1
2
only:
- master

也可以根据当前的代码变动是合并,还是推送,还是使用API来触发的。
如果一个任务没有only属性,那默认就是
only: [‘branches’, ‘tags’] 操作分支或者tags都会触发流水线。

before_script
before_script 关键词是用于在每个任务之前执行的脚本,但是会在artifacts恢复之后执行。你可以这样定义一个全局的before_script,

1
2
3
default:
before_script:
- echo "Execute this script in all jobs that don't already have a before_script section."

也可以在一个任务中中单独定义

1
2
3
4
5
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就不会被执行了,目前官方正在计划这个特性。
可以定义全局的,也可以定义局部的

1
2
3
4
5
6
7
8
9
10
11
12
13
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从哪里下载,
这里有一个例子,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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的方式定义

1
2
3
4
5
deploy to production:
stage: deploy
script: git push production HEAD:master
environment:
name: production

需要注意的是这里定义的环境变量是不能在script值使用的。
这个关键词可以和review和merge搭配。

extends
这个关键词可以使一个任务继承另一个任务。
如下案例

1
2
3
4
5
6
7
8
9
10
11
12
13
.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中,
合并后的结果是

1
2
3
4
5
6
7
8
rspec:
script: rake rspec
stage: test
only:
refs:
- branches
variables:
- $RSPEC

使用这一个手段,可以写一个模板,只要稍微改改就能后使用。非常适合大批量编写流水线。

include
使用include可以导入一个或多个额外的yaml文件到你的CICD配置里,这一你就可以将一个很长的流水线,分隔出来。使用include来引入。
也可以将几个流水线中相同的配置,提取出来,公用。引入的文件扩展名 必须是.yaml或者.yml两种,其他的不行。
include 关键词下,有四个可选性,
local, 引入一个当前项目的文件
file, 引入一个不同项目的文件
remote, 引入一个公网文件,
template, 引入一个由GitLab提供的模板

下面是几个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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.
项目这个是一个多项目流水线

1
2
3
4
5
6
7
rspec:
stage: test
script: bundle exec rspec

staging:
stage: deploy
trigger: my/deployment

流水线执行完test任务后就会去执行my/deployment项目的流水线

配置下游流水线式也可以执行分支

1
2
3
4
5
6
7
8
9
rspec:
stage: test
script: bundle exec rspec

staging:
stage: deploy
trigger:
project: my/deployment
branch: stablez

rules
rules是用于规定任务的执行规则,使用一个表达式,来规范那些任务执行,那些任务不执行.还可以在任务成功,或者失败后,触发另一个任务。
如下面这个例子

1
2
3
4
5
6
7
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等。可以针对不用的情景配置不用的规则。
再看下这个例子

1
2
3
4
5
6
job:
script: echo "Hello, Rules!"
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
when: manual
allow_failure: true

解释起来并不复杂,一个判断语句,二句赋值语句。即如果当前分支是master,在任务的执行方式改为手动,并且运行失败。

allow_failure
allow_failure是一个布尔类型, true或false, 默认为false,表示当前任务是否允许失败。有这样一个应用场景,在使用eslint检查代码的时候,如果团队管理松散,可以将在eslint的任务下设置allow_failure: true,(其实这样还不如去掉这个任务那,手动狗头) 这样即使这个任务报错了,流水线也会继续往下走。如果一个任务设置了allow_failure: true,并且这个任务报错了,那么它将会显示黄色警告。但有种情况任务失败了也会停止的, 那就是任务设置了when: manual,即手动操作的任务。手动启动的任务,报错了就会停止,不会继续执行后续任务,除非在rule设置报错的处理逻辑。

coverage
coverage 是用于获取项目的代码覆盖率,这个配置项的值只能是一个正则表达式,官方有提供一些,在CICD的General pipelines里
覆盖率可以添加到项目的readme上,像这样的。

pages
pages是一项特殊的工作,用于将静态内容上传到GitLab,可用于为您的网站提供服务,其实就是可以托管你的网站。它具有特殊的语法,因此必须满足以下两个要求:

任何静态内容都必须放在public/目录下。
制品artifacts必须是目录public/,就是编译后的文件必须存放在public中
下面的示例将所有文件从项目的根目录移至public/目录。这里必须先创建一个.public 目录,防止根目录下已经存在public了,导致循环复制。

1
2
3
4
5
6
7
8
9
10
11
pages:
stage: deploy
script:
- mkdir .public
- cp -r * .public
- mv .public public
artifacts:
paths:
- public
only:
- master

release
release关键词是用于创建一个release,即创建一个发布,
创建一个发布,可以配置这些内容

  • tag_name tag 名称
  • description 描述
  • name 名称
  • ref 提交的hash值
  • milestones 要关联的里程碑
  • released_at 创建时间
    1
    2
    3
    4
    5
    6
    ios-release:
    script:
    - echo 'iOS release job'
    release:
    tag_name: v1.0.0-ios
    description: 'iOS release v1.0.0'
    resource_group
    有时在环境中同时运行多个作业或流水线时可能会导致在部署过程中出错。

为了避免这些错误,resource_group可以使用该属性来确保运行程序不会同时运行某些任务。资源组的行为类似于其他编程语言中的信号灯。

当一个任务设置了resource_group , 同一项目的不同管道之间任务的运行是互斥的。如果属于同一资源组的多个任务同时进入队列,则运行程序仅选择其中一个作业。其他作业将等到 resource_group释放。

1
2
3
deploy-to-production:
script: deploy
resource_group: production

在这种情况下,两个deploy-to-production单独流水线中的两个作业永远无法同时运行。最后的结果及时你可以确保永远不会在生产环境中发生并发部署。

您可以为每个环境定义多个资源组。例如,当部署到物理设备时,您可能有多个物理设备。可以将每个设备部署到,但是在任何给定时间每个设备只能部署一个。

resourcegroup值只能包含字母,数字,-, , /, $, {, }, .,和空格。它不能以开头或结尾/。

retry
retry可以设置一个任务的重试次数,值的类型是数字 最大是2,如果设置2,就表明该任务最多可以执行3次,其中包括2次重试。对于网络不稳定的部署,非常有用。

1
2
3
test:
script: rspec
retry: 2

timeout
timeout是用于设置一个任务的超时时间,
你也可以设置一个项目级别的超时时间。在CICD的设置中

1
2
3
4
5
6
7
build:
script: build.sh
timeout: 3 hours 30 minutes

test:
script: rspec
timeout: 3h 30m

variables
variables可以让你在yaml文件中定义变量,变量可以设置全局的,也可以是单个任务内定义。然后在script或者执行的命中使用,定义和使用的示例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
variables:
DEPLOY_SITE: "https://example.com/"

deploy_job:
stage: deploy
script:
- deploy-script --url $DEPLOY_SITE --path "/"

deploy_review_job:
stage: deploy
variables:
REVIEW_PATH: "/review"
script:
- deploy-review-script --url $DEPLOY_SITE --path $REVIEW_PATH

打赏

扫一扫,分享到微信

微信分享二维码

请我喝杯咖啡吧~

支付宝
微信