看过前文的博友可能注意到我是把 部署 dll 文件拷贝到生产机器, 之后在生产机器上使用 docker-compose 即时创建镜像, 并没有完成 CI/CD, 只是在原来传统部署方式下 将部署文件容器化.
经过长时间实操验证, 终于完成基于 GitLab 的 CI/CD 实践, 本次实践的坑位很多, 实操的过程尽量接近 最佳实践 (不做 hack, 不做骚操作), 记录下来也方便自己加深理解.
第一部分: GitLab CI/CD 原理 和 GitLab Runner 安装 (这里使用 shell 执行器)
第二部分: GitLab CI/CD 实践:
宏观项目架构图
解决方案开发目录
.GitLab-ci.YAML 文件
项目部署目录
第一部分: GitLab CICD 原理
1 GitLab CI/CD 架构:
GitLab CI/CD 存储 [定义的构建] 和 [构建状态] 的 API 应用程序, 提供友好的界面管理项目构建, 构建过程由 .GitLab-ci.YAML 文件定义, 而这个文件一般置于代码仓库的根目录.
GitLab Runner 执行构建过程的应用程序, 可与 GitLab Server 形成分布式部署, 如上图所示, 其通过 API 与 GitLab Server 交互
2 GitLab CI/CD 配置界面 & GitLab Runner 安装
GitLab CICD 的界面配置权限取决于你在 GitLab server 中的角色, 我的角色 https://docs.gitlab.com/ee/user/permissions.html 是 maintainer, 足够创建自定义的 runner.
本次演示的是创建自定义 Runner,GitLab runner 安装完毕, 很明显现在需要与 GitLab 项目建立联系, 这就是向 GitLab runner 注册项目的过程.
注册时需要关注的两个配置是:
tags 可理解为与这个 Runner 有关的 Pipeline 任务, 在. GitLab-ci.YAML 要用到
runner executor: 可理解为执行的初始环境, 这里使用 shell 方式
注册过程和结果请参考下图:
第二部分: 基于 docker-compose 的 GitLab-CI 实践
1 项目架构图
我们的目标是在部署机器上使用 docker-compose 拉取 GitLab CI 生成的 ReceiverAPP, webAPP 远端镜像, 快速产生容器.
对每一次提交或合并都会执行 build 任务, 形成 Continous Intergation
对 Git: tag 会执行 build_Image 任务, 上述两个任务都成功, 会自动执行 deploy_staging 任务, 这样就能形成基于 Git:tag 的部署版本管理 (部署出错, 也能很快回滚到上次的部署 tag)
本处使用 GitLab Runner 服务器作为 staging 部署机器; 原则上不允许随意部署 Prod, 常规让开发人员手动登陆到 Prod 机器上执行部署命令, 以下 GitLab-CI 也没有完成 Prod 的自动部署过程, 自行补上登陆终端的脚本即可.
2 开发目录
.GitLab-ci.YAML 需要放置在仓库根目录下, 以下. GitLab-CI.YAML 文件定义了 src 目录下 EqidManager , EqidReceiver 两个项目的构建过程, 写. GitLab-ci.YAML 的过程就是 将平日里使用 docker 打包镜像并发布的行为 脚本化.
├── container
── App/Dockerfile
── receiver/Dockerfile
├── docker-compose.dcproj
├── docker-compose.override.YAML
├── docker-compose.YAML
├── .dockerignore
├── .env
├── Eqid-Manager.sln
├── .Git
├── .gitattributes
├── .gitignore
├── .GitLab-ci.YAML
├── NuGet.Config
├── src
── EqidManager
── EqidReceiver
└── test
── EqidProxyServer.Tests
3 .GitLab-ci.YAML 文件
对比开发目录, 我们定义了 build-->build_image-->deploy 三个任务, 某些任务还包括不同分支 Job:
- stages:
- - build
- - build_image
- - deploy
- variables:
- # CI_DEBUG_TRACE: "true" # 增加调试追踪
- deploy_path: "/home/xxxx/eqidmanager"
- before_script:
- - "docker info"
- build:
- stage: build
- script:
- - "for d in $(ls src);do echo $d;prog=$(pwd)/src/$d/$d.csproj; dotnet build $prog; done"
- tags: # 这里必须是字符串数组
- - another-tag
- build_image:EqidManager:
- stage: build_image
- script:
- - dotnet publish src/EqidManager/EqidManager.csproj -c release -o ../../container/App/publish/
- - docker build --pull -t $CI_REGISTRY_USER/eqidmanager:$CI_COMMIT_REF_NAME container/App
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
- - docker push $CI_REGISTRY_USER/eqidmanager:$CI_COMMIT_REF_NAME
- tags:
- - another-tag
- only: # 构建策略
- - tags
- build_image:EqidReceiver:
- stage: build_image
- script:
- - dotnet publish src/EqidReceiver/EqidReceiver.csproj -c release -o ../../container/receiver/publish
- - docker build -t $CI_REGISTRY_USER/eqidreceiver:$CI_COMMIT_REF_NAME container/receiver
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
- - docker push $CI_REGISTRY_USER/eqidreceiver:$CI_COMMIT_REF_NAME
- tags:
- - my-tag
- only:
- - tags
- deploy:staging:
- stage: deploy
- script:
- - cd $deploy_path
- - export TAG=$CI_COMMIT_REF_NAME # 引入本次 CI 的 tag 名称, 覆盖. env 文件默认配置
- - "docker-compose build" # 根据 docker-compose 命令的用法, 会自动 merge docker-compose.YAML 和 override 文件
- - "docker-compose up -d"
- tags:
- - my-tag
- deploy:prod:
- stage: deploy
- script:
- - # TODO 需要写脚本登陆到 Prod 机器上
- - export TAG=$CI_COMMIT_REF_NAME
- - cd $deploy_path
- - "docker-compose build"
- - "docker-compose up -d"
- tags:
- - my-tag
- when: manual
这里有些知识点和 坑位需要指出:
第 8 行: 预先定义的环境变量, 该变量定义 GitLab CD 的部署目录
第 16 行: 对 src 开发目录下两个程序执行 dotnet build 命令
第 17 行: tags 定义具备该 tags 的 Runner 可以执行该任务, 注意这里的 tags 必须是字符串数组
第 23-26 行: 常规构建镜像并推送到镜像仓库的过程, 用到
- 密钥环境变量 CI_REGISTRY_USER,CI_REGISTRY_PASSWORD , 可在 GitLab-CI 界面配置
- 预定义环境变量 CI_COMMIT_REF_NAME, 该变量标记构建项目的分支或 tag 名称, 与下方的 only 形成呼应
- 注意变量可被重写, 重写有优先级 http://www.ttlsa.com/auto/gitlab-cicd-variables-zh-document/
第 29 行; only 定义此 Job 只在 Git:tags 时执行, 也就是说切出 tag, 才会构建镜像
第 47 行: Gialab-ci pipeline 每个 stage 都会重新拉取 Git 源码执行 pipeline 任务, 我们不能在 GitLab Runner 的工作目录下部署项目, 这也是上面我们定义 deploy_path CI 变量的原因
第 48 行: 注入本次 GitLab CI 标签名, 实际上是覆盖了. env 同名环境变量
第 49 行: 部署目录会定义 docker-compose.YAML 和 docker-compose.override.YAML 两个文件, 前者用于容器服务的易变配置, 后者定义 容器服务的基础配置, docker-compose 命令会自动 merge 这 2 个文件
更多 GitLab-CI 的用法: https://docs.gitlab.com/ee/ci/yaml/
4 Continous Deploy 部署目录
在 staging 机器的 deploy_path 目录下建立了如下部署文件:
其中 appsetting.secrets.JSON 和 receiver.secrets.JSON 会在 dccker-compose.YAML 中被挂载, 这也是一种原则: 密钥文件不要进入 Git 的代码管理
├── appsettings.secrets.JSON
├── docker-compose.override.YAML
├── docker-compose.YAML
├── .env
├── EqidManager.db
├── nginx
│ ├── Dockerfile
│ └── nginx.conf
└── receiver.secrets.JSON
dockee-compose 默认会使用同级目录下的. env 文件, 这个文件存储相对固定的环境变量:
----- .env 文件 ----
- TAG=master # 该 TAG 变量会在 CI:deploy_staging 脚本中被覆盖
- docker_host=172.16.1.1
- COMPOSE_PROJECT_NAME=EqidManager
- DOCKER_REGISTRY=***
这样 staging 部署环境也准备完毕, 依据. GitLab-ci.YAML 文件定义的 deploy_staging 脚本:
跳转到部署目录 ---> 应用本次 GitLab-ci 的 Git:tag----> 执行 docker-compose 命令拉取镜像并部署.
作者: JulianHuang
码甲拙见, 如有问题请下方留言大胆斧正; 码字 + Visio 制图, 均为原创, 看官请不吝好评 + 关注, ~..~
来源: https://www.cnblogs.com/JulianHuang/p/11346615.html