“烤鸡”第三步、Docker下的GitlabCI构建实战

本文概要和目录

机器有了,docker基础环境用了,现在我们来用docker 部署 gitlab 并且以一个标准的前端工程实战 一个 CICD 流程

安装Gitlab

安装gitlab是我们的重中之重

  • 从docker 拉下来
docker pull gitlab/gitlab-ce
复制代码
  • 配置它
$ sudo docker run --detach \
  --hostname gitlab.example.com \   # 设置主机名或域名 注意⚠️ 这个地方最好设置成你的内网Ip哈
  --publish 443:443 --publish 80:80 --publish 22:22 \ # 本地端口的映射
  --name gitlab \     # gitlab-ce 的镜像运行成为一个容器,这里是对容器的命名
  --restart always \  # 设置重启方式,always 代表一直开启,服务器开机后也会自动开启的
  --volume /srv/gitlab/config:/etc/gitlab \   # 将 gitlab 的配置文件目录映射到 /srv/gitlab/config 目录中
  --volume /srv/gitlab/logs:/var/log/gitlab \ # 将 gitlab 的log文件目录映射到 /srv/gitlab/logs 目录中
  --volume /srv/gitlab/data:/var/opt/gitlab \ # 将 gitlab 的数据文件目录映射到 /srv/gitlab/data 目录中
  gitlab/gitlab-ce:latest  # 需要运行的镜像


# 443:443:将http:443映射到外部端口443
# 9000:80:将web:80映射到外部端口9000
# 22:22:将ssh:22映射到外部端口22

# 最终我调整好的
docker run -d  --hostname 192.168.1.5 -p 443:443 -p 80:80 -p 233:233 --name gitlab --restart always -v/srv/gitlab/config:/etc/gitlab -v /srv/gitlab/logs:/var/log/gitlab -v /src/gitlab/data:/var/opt/gitlab docker.io/gitlab/gitlab-ce
复制代码

除此之外你还需要去更改配置 ,要不然你的git仓库的地址就是默认的git@gitlab.example.com://xxx , 但是正确的地址应该是你自己的ip地址, 设置的方式也非常的简单

# 先修改ssh地址
# 还记得我们之前的地址吗  -v /home/gitlab/config: /etc/gitlab  现在你去到 ,修改rb 
$ vim /home/gitlab/config/gitlab.rb

gitlab_rails['gitlab_ssh_host'] = '192.168.52.129' 改成你自己的ip地址
++++

# 改完之后要进入容器 bash重启 这个容器里的gitlab应用
$ docker exec -it gitlab /bin/bash
$ gitlab-ctl reconfigure
$ gitlab-ctl restart

# 再修改http地址
$ vim /home/gitlab/data/gitlab-rails/etc/gitlab.yml

host:  192.168.52.129

# 改完之后要进入容器 bash重启 这个容器里的gitlab应用
docker exec -it gitlab /bin/bash
gitlab-ctl restart

复制代码
  • 关于密码

gitlab启动之后,在这里可以看到root的密码,记得登录之后去修改密码哈,我们有一个简单的命令可以查看(因为我们是docker安装的所以比较简单,如果不是docker安装的同学,你需要找别的方法哈)

$ sudo docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password
复制代码
# 当你作完上面的操作之后,
# 运行下面的命令 当你能看到gitlab容器的时候,就意味着你的容器跑起来了,接下来去输入的宿主机的ip就能通过web访问了

root@joney-N8xEJEK:~# docker ps
asCONTAINER ID   IMAGE                         COMMAND                  CREATED       STATUS                PORTS                                                                              NAMES
989f74cd9bbc   gitlab/gitlab-ce:latest       "/assets/wrapper"        4 weeks ago   Up 7 days (healthy)   0.0.0.0:80->80/tcp, :::80->80/tcp, 22/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   gitlab
root@joney-N8xEJEK:~# 
复制代码

GitlabCI

万事具备之后,接下来我们来做CI 流程 (基于GitlabCI),这里是最简单的实现,还有很多功能没有实现在后续的文章中我们会一点点的优化。本文实现的功能如下(GitlabCI + docker + React + 飞书群机器人)

首先我们来介绍一下GitlabCI

所谓的CI 就是自动化 构建,指的是你写完代码之后,提交到仓库,触发了某个事件,然后接下来服务器会自动的去构建你的程序,CD指的是你在你自动构建了程序之后的自动发布操作

概念讲解

  1. 我们可以通过配置项目下不同的 .gitlab-ci.yml 文件 来,实现不同项目的不同CI流程,它大概长这个样子
stages: # 分段
   - package
   - install
   - lint
   - build
   - deploy

cache: # 缓存
   paths:
       - node_modules
       - build
       - gitlab_test_ci.tar

package-job: # job1
   tags:
       - hot
   only: 
       - develop
       - release
       - master
   stage: package
   script:
       - npm config set registry https://registry.npm.taobao.org/

install-job: # job2
   tags:
       - hot
   only: 
       - develop
       - release
       - master
   stage: install
   script:
       - npm install

lint-job: # job3
   tags:
       - hot
   only: 
       - develop
       - release
       - master
   stage: lint
   script:
       - npm run prettier-format
       - npm run lint
复制代码
  1. Pipeline & Job,Pipeline是Gitlab根据项目的.gitlab-ci.yml文件执行的流程,它由许多个任务节点组成, 而这些Pipeline上的每一个任务节点,都是一个独立的Job

Job在YML中的配置我们将会在下面介绍,现在需要知道的是:每个Job都会配置一个stage属性,来表示这个Job所处的阶段。

一个Pipleline有若干个stage,每个stage上有至少一个 Job,如下图所示:

  1. 谁去运行我们这些job 呢?

当我们了解上述的基础概之后,我们来思考一个问题,谁负责去完成我们这些工作呢?答案揭晓,负责这些工作是一个小的程序,它就是gitlab-runner,专门为gitlab-ci而生,在这个程序上可以运行很多job。当然了它一般上需要经过一些配置才能使用 ,具体如何使用请见下文。

Runner可以分为两种: Specific Runne (左边的) 和 Shared Runner (右边的)

Shared Runner是Gitlab平台提供的免费使用的runner程序,它由Google云平台提供支持,每个开发团队有十几个。对于公共开源项目是免费使用的,如果是私人项目则有每月2000分钟的CI时间上限。

Specific Runner是我们自定义的,在自己选择的机器上运行的runner程序,gitlab给我们提供了一个叫gitlab-runner的命令行软件,只要在对应机器上下载安装这个软件,并且运行gitlab-runner register命令,然后输入从gitlab-ci交互界面获取的token进行注册, 就可以在自己的机器上远程运行pipeline程序了。

Shared Runner 和 Specific Runner的区别
Shared Runner是所有项目都可以使用的,而Specific Runner只能针对特定项目运行
Shared Runner默认基于docker运行,没有提前装配的执行pipeline的环境,例如node等。而Specific Runner你可以自由选择平台,可以是各种类型的机器,如Linux/Windows等,并在上面装配必需的运行环境,当然也可以选择Docker/K8s等
私人项目使用Shared Runner受运行时间的限制,而Specific Runner的使用则是完全自由的。

Executor 概念

什么是Executor? 我们上面说过 Specific Runner是在我们自己选择的平台上执行的,这个平台就是我们现在说到的“Executor”,为了简单起见,我们没有选择docker 而是选择了shell。我把官方文档的对比图也一并贴出来,供大家参考和选择 适合自己的

参考链接:docs.gitlab.com/runner/exec…

  1. .gitlab-ci.yml 基础的知识扫盲. 以便于你更快的上手

在正式开始之前我希望你对下面的概念有一定的理解 ,gitlab-runner 就是依据 .gitlab-ci.yml 文件一步一步去执行的

stages: 
    - package  # 这些和1.处的标记一一对应 表示要进行哪些阶段
    - lint
    - build
    - deploy

cache: # 缓存设置
    paths:
        - node_modules
        - build
        - gitlab_test_ci.tar

package-job: # job1 
    tags:  # tag标记,你要在那个指定的tag上去运行你的runner,大白话:你要把这个job丢到那个tag表示的runner中运行
        - hot
    only:   # 标记这个job 上在那个分支上有效
        - develop
        - release
        - master
    stage: package  # 1. 处标记,表示这个job的 stages 到底是什么
    script:  # 你所要执行的shell命令
        - npm config set registry https://registry.npm.taobao.org/

#....下面还有更多的job 但是大多数情况下 就是这样的 结构
复制代码

实战操作

好了,现在让我们从github上拉取 一个既有仓库,来完成CI的配置和运行,(这个github仓库是我自己的初始化的一个React-Ts基础结构包含了lint 和commit 和eslint 以及peptic,至于这个是如何构建的我们这里不关心,我们会开另一个文章来介绍它)。接下来我们准备其他的材料

  1. 首先 我们有了一个 github的一个react模板 ,它包含了一些基础的功能.
  2. 我们搭建好了自己的gitlab ,现在我们把这个react模板上次到自己的gitlab仓库 中去 .
  3. 为我们仓库配置好runner .
  4. 开始编写.gitlab-ci.yml .
  5. 进行调试好运行 .
  • 拉取先有一个react-ts模板 ,并且 上传到自己的gitlab仓库.
$ git clone https://github.com/BM-laoli/react-ts-template
$ cd react-ts-template 
$ git checkout react-tpl
# 这一步执行之前,你需要在自己的gitlab建立一个仓库
$ git remote add org  http://192.168.1.5/bigfe/ci-react-pc-test.git 
$ git checkout -b develop

# 拉取一个develop 分支来搞
$ git push org develop 
复制代码
  • 配置runner

下载runner,这里我并没有把runner 丢到docker中,直接放了宿主机,主要原因是docker上跑runner 然后 如果涉及再去build docker image和对宿主机的操作交互十分的麻烦(本人比较的蔡。搞了一个多礼拜没有什么结果,然后放弃了),果断把runner 跑在宿主机中

# Linux x86-64
$ sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64

$ sudo chmod +x /usr/local/bin/gitlab-runner

$ sudo gitlab-runner install  --working-directory=/home/gitlab-runner

$ sudo gitlab-runner start
复制代码

配置它,首先我们我们打开 gitlab上面的项目 ,依据图示找到它

然后?的几个参数很重要

$ sudo gitlab-runner register
# 然后 依据命令行就来.... 至于所要填写的参数都在上面的图中能够找到, 特别需要说明的就 是 tag 我们这里先随意写一个就叫hot
# 完成上面的操作之后,输入下面的命令进行执行
$ sudo gitlab-runner verify --delete

# 这个时候你可直接进入runner 进行观察,看看哪些job在跑,哪些job失败了,失败原因是什么。我这里遇到一个bug 就是piple一直没动静,跑不动,再我run 进runner之后,它就好了。
$ sudo gitlab-runner run

复制代码

按照上面的操作一番之后,我们来到gitlab 如果显示的绿色就说明ojbk了,我们来搞定下面的任务

  • 编写.gitlab-ci.yml

每个项目都有不同的部署要求,所以yml也并不是一成不变的,我这里是按照下面的场景设计实现的

主要是两个大的阶段,最后使用node 把build的静态文件 访问打开

阶段1 前端框架的打包:

首先先给ci安装nodejs环境好设置npm镜像,然后下载node_modules,而后 使用代码格式化lint 进行格式验证 ,再然后使用前端的ci工具,build 一下把静态文件打包出来;

阶段2 把静态文件cv到docker image中

使用node启动一个静态资源服务 供外部访问:使用Dockerfile把静态文件 cv到一个装有nodejs 环境的docker image中。
最后把容器run 起来,并且完善 容器的更新和 自动重启升级

.gitlab-ci.yml

# @format

# 执行前配置环境 【package】
# node_module install 【install】
# 检查husky ,代码格式化 ,检查eslint  【lint】
# docker (容器包,这里指的是node下的一个ngx类似的?它就是我们) 【docker】
# run docker ( 走一个 执行docker 文件 )【rundocker】

# 需要给定一些变量控制ci/cd的执行 但这里就先没写了

stages: # 分段
    - package
    - install
    - lint
    - build
    - deploy

cache: # 缓存
    paths:
        - node_modules
        - build
        - gitlab_test_ci.tar

package-job:
    tags:
        - hot
    only: 
        - develop
        - release
        - master
    stage: package
    script:
        - npm config set registry https://registry.npm.taobao.org/

install-job:
    tags:
        - hot
    only: 
        - develop
        - release
        - master
    stage: install
    script:
        - npm install

lint-job:
    tags:
        - hot
    only: 
        - develop
        - release
        - master
    stage: lint
    script:
        - npm run prettier-format
        - npm run lint

build-job:
    tags:
        - hot
    only: 
        - develop
        - release
        - master
    stage: build
    script:
        - npm run build
        # 给定一个 path 的到一个build 目录
        # 由于gitlab的CI 默认会delete job的产物,所以这里我们使用cache来缓存一部分内容
        # 供后续的job 使用
        
deploy-job: #  这里的操作主要就是 在runner中拿到build发送到远端服务器,然后在远端服务器 进行docker image的构建操作
    tags:
        - hot
    only: 
        - develop
        - release
        - master
    stage: deploy
    script:
        - docker image build -t gitlab-runner-ci-test .
        # 先停止运行的容器 然后 马上更新这个容器 使用 shell脚本去运行
        - sshpass -p "your-password" chmod 777 build.sh
        -  ./build.sh

# 这里你可以根据你自己的实际情况去更改 到底是部署到dev 还是 pre 或者是 prd 环境,在我司,这里还会有一个 preBuld.sh 脚本去 构建本地环境,注入api地址,这样就做到了 环境可配置功能
# deploy-job: #  这里的操作主要就是 在runner中拿到build发送到远端服务器,然后在远端服务器 进行docker image的构建操作
#     tags:
#         - hot
#     stage: deploy
#     only: 
#         - master
#     script:
#         - docker image build -t gitlab-runner-ci-test .
#         # 先停止运行的容器 然后 马上更新这个容器 使用 shell脚本去运行
#         - sshpass -p "your-password" chmod 777 build.sh
#         -  ./build.sh
复制代码

dockerfile

# 获取node环境
# 获取npm
# 获取serve
# cv build文件 
# 执行run 命令

# ssh 容器跑起来
FROM node:alpine
COPY ./build /app
WORKDIR /app
RUN npm config set registry https://registry.npm.taobao.org 
RUN npm install serve -g
CMD ["serve", ".", "-p", "3002"]
EXPOSE 3002

复制代码

build.sh
这里说明一下为什么还需要脚本,主要原因是docker容器更新的时候为了减少体积消耗 和 container 重复 container冲突等问题, 也是依据它我们才能完成 image的重启和版本迭代

#!/bin/bash
##############################################################
# 如果 container 不存在就创建 如果存在就update
##############################################################
docker stop gin-gotest

docker container rm -f $( docker ps -aq --no-trunc  --filter name=gin-gotest)

if [[ "$?" -eq '0' ]]; then
  docker container run --name=gin-gotest -d -p 8200:8000 go-gin
  echo "更新成功"
else
  docker container run --name=gin-gotest -d -p 8200:8000 go-gin
  echo "初始化成功"
fi

echo "部署完成"
复制代码
  • 运行和调试

可以看到经过多次尝试之后我们总算成功了,现在让我们来点别的花样,比如给流程加一个飞书的群提示 机器人(主要是飞书的文档配置了一个webhook),我们需要按照文档,先创建一个群,然后按照图示操作 结合飞书官方文档配置一下就好了,比如我这里是一个非常简单的只是 配置了一段连接而已, 由于我们使用的webhook机制,所以我们配置好之后,先用postman试一下,如果么问题,那么你的飞书机器人将会被触发。 现在我们把它丢到 ci流程中去, 这里我丢到之后一个build success阶段,如果成功就在群里通报

#!/bin/bash
##############################################################
# 如果 container 不存在就创建 如果存在就update
##############################################################
docker stop gin-gotest

docker container rm -f $( docker ps -aq --no-trunc  --filter name=gin-gotest)

if [[ "$?" -eq '0' ]]; then
  docker container run --name=gin-gotest -d -p 8200:8000 go-gin
  echo "更新成功"
else
  docker container run --name=gin-gotest -d -p 8200:8000 go-gin
  echo "初始化成功"
fi

echo "部署完成"

# 发送飞书通知,后续需要写一个服务 集成 自己的 账户体系
curl --location --request POST 'https://open.feishu.cn/open-apis/bot/v2/hook/youer-authkey' \
--header 'Content-Type: application/json' \
--data-raw '{
    "msg_type": "post",
    "content": {
        "post": {
            "zh_cn": {
                "title": "项目更新通知",
                "content": [
                    [
                        {
                            "tag": "text",
                            "text": "项目有更新: "
                        },
                        {
                            "tag": "a",
                            "text": "请查看",
                            "href": "http://192.168.1.5/big_ef/gitlab_test_ci"
                        }
                    ]
                ]
            }
        }
    }
}'
---
复制代码

总结

关于gitlab-runner 是迄今为止 本人接触过的比较简单成本比较低的CICD工具了,大多数的CICD工具都是如此,希望同学们好好学习,特别是Shell脚本的编写,作为一名开发不管是前端或者后端shell脚本编写是必备技能啊

参考连接

阮一峰Docker入门

Docker中文社区

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享