使用 CircleCI 2.0 进行持续集成/持续部署

image.png

“从功能开发完成直到成功部署”这一阶段被称为软件开发“最后一公里”,很多开发团队也越来越认识到,持续集成和持续部署可帮助开发团队提高迭代效率和质量。

持续集成和持续部署工具层出不穷,CircleCI 就是这类工具中比较优秀的一个。

什么是持续集成

持续集成(Continuous Integration)通常缩写为 CI,
持续集成指的是,当代码有变更时,立即进行构建和测试,反馈运行结果,我们可以根据测试结果,确定新代码是否可以和原有代码正确的集成在一起。
让你能够在开发中随时发现问题,在快速的产品迭代中还可以保持很高的质量。因为修复问题的成本随着时间的推移而增长,越早发现,修复成本越低。

什么是持续部署

持续部署(Continuous Deployment)通常缩写为 CD,
持续部署指的是,当代码有变更时,自动进行测试和构建,如果一切顺利则自动部署到服务器上。

CircleCI 是什么

CircleCI 是一个持续集成/持续部署的服务,开源项目可以免费使用,他的价格取决于你需要并发构建实例的数量,单个实例是免费的。

CircleCI 能做什么

他可以绑定 GitHub/Bitbucket,只要你的代码有变更,就会自动抓取,根据你的配置,提供运行环境,执行测试、构建和部署。

CircleCI 的工作流程

image.png

PHP 项目 使用CircleCI 自动部署到 AWS ECS

一. 前期准备

  • GitHub/Bitbucket 帐号
  • 该帐号下面有一个项目

二. CircleCI 配置

1.添加配置文件

要使用 CircleCI,首先在你项目的根目录创建一个名为.circleci的文件夹,并新建config.yml文件

2.在 CircleCI 设置你的构建环境

打开 CircleCI 控制台 选择左侧的 Add Project , CircleCI 会列出你的 GitHub/Bitbucket 的所有项目,选择项目并单击 Set Up Project 按钮

image.png

选择合适的操作系统(Operating System)、合适的编程语言(Language) (本文使用的是 Linux/PHP)

复制下面的示例配置文件到你自己的配置文件中,推送到 git 仓库,然后就可以点击 Start building 进行第一次构建了。

image.png

三. CircleCI 配置文件

CircleCI 配置文件一般由三部分组成

  • 版本 (version)

    • 你要使用的 CircleCI 版本
  • 工作 (jobs)

    • 你要执行的 job 清单,集合中的键为 job 的名称,值是具体执行 job 的内容,如果你使用工作流(workflows),则 job 的名称在配置文件中必须唯一,如果你不使用 工作流(workflows),则必须包含名称为build的 job 来作为用户提交代码时的默认 job。
  • 工作流(workflows)

工作 (jobs)

首先我们来先写一个基础的配置文件

# PHP CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-php/ for more details
#
version: 2
jobs:
  build:
    docker:
    - image: circleci/php:7.1-browsers
    # 必要时可以在这里指定依赖镜像
    # - image: circleci/mysql:9.4

    working_directory: ~/repo

    steps:
    - checkout
    - run: composer install -n --prefer-dist

    # 运行单元测试
    - run: phpunit
  deploy:
    docker:
    - image: circleci/python:3.6.1

    working_directory: ~/repo

    steps:
    

在上面的列子中,有两个 job 叫 build/deploy,现在讲解一下 job 里面的属性

  • docker 键是用来指定 CircleCI 当前 job 使用 docker, 其值image是指 docker 所使用的镜像,必要时你可以同时指定多个镜像,比如你的项目需要依赖 mysql 或者 redis。 第一个列出的容器为主容器,steps 都会在主容器中进行。

    • CircleCI 预先定义了很多镜像,您可以在 此处 找到它们
    • 如果不想使用 docker 也可以使用 machine / macos 具体使用方法参考 这里
    • 关于 docker 键的其他属性与用法 你可以在 此处 找到
  • working_directory 属性是用来定义steps 在哪个目录运行

  • steps 当前 job 要运行的 命令 (command) 列表

步骤 (steps)

steps 将负责对环境的初始化,与项目的构建、部署和测试:

一. 构建、测试

  1. 检出代码

    # 将分支中的代码检出到 working_directory 
    - checkout
    # 让步骤中可以调用其他 docker
    - setup_remote_docker
    
  2. 从缓存中恢复 composer 依赖目录

    - restore_cache:
        keys:
        - v1-dependencies-{{ checksum "composer.json" }}
        # 如果没有匹配的缓存则使用最新的缓存
        - v1-dependencies-
    

    我们可以使用缓存功能来避免每次都重新 composer install,可以节约大量时间

    {{ checksum "filename" }} 
    

    这部分指的是,给 filename 这个文件的文件内容 Base64 后取 SHA256 hash
    其他模版语法请查看 官方文档

    • 我们使用了两个缓存的 key 第一个是精确匹配设置的缓存 key,第二个是当用户修改 composer.json 文件时,我们不能精确匹配缓存,这时候恢复最近的一次缓存
  3. 安装依赖

    - run:
        name: Install local dependencies
        command: composer install -n --prefer-dist
    

    如果上一步恢复缓存的时候已经恢复了这些依赖项,则这步将非常快。

  4. 缓存依赖

    - save_cache:
        paths:
        - ./vendor
        key: v1-dependencies-{{ checksum "composer.json" }}
    

    经历了上一步,我们就会有一份当前版本完整的依赖目录,路径为vendor,这时我们把它缓存起来方便下次使用

  5. 测试

    - run:
        name: Testing
        command: phpunit
    

    我们运行测试的命令,如果测试有任何不通过则本次构建将失败。

  6. 打包 docker 镜像

    - run:
        name: Build image
        command: |
            docker build -t $FULL_IMAGE_NAME .
            mkdir docker-image
            docker save -o docker-image/image.tar $FULL_IMAGE_NAME
    

    打包 docker 镜像并命名为 $FULL_IMAGE_NAME,并将镜像 保存成 tar 归档文件

  7. 运行并简单测试镜像

    - run:
        name: Test image
        command: |
          docker run -d -p 8080:80 --name built-image $FULL_IMAGE_NAME
          sleep 10
          docker run --network container:built-image byrnedo/alpine-curl -I --retry 10 --retry-connrefused http://localhost
    

    运行刚才打包好的镜像,然后使用 curl 对打包好的镜像进行简单测试

  8. 保存镜像到是临时文件

    - persist_to_workspace:
        root: .
        paths:
        - docker-image
    

    保存刚才镜像 tar 归档文件到 workspace,以便 build job 使用

二. 部署

  1. 检出代码

  2. 加载构建好的 docker 镜像

    - attach_workspace:
        at: workspace
    - run:
        name: Load image
        command: |
          docker load --input workspace/docker-image/image.tar
    

    挂载 workspace 到当前 job, 挂载后 当前 job 的 workspace/docker-image/image.tar 为上一步打包出的 docker 镜像

    使用 docker load 导入镜像

  3. 安装 aws cli

    - restore_cache:
        key: v1-{{ checksum "requirements.txt" }}
    - run:
        name: Get Aws-cli
        command: |
        python3 -m venv venv
        . venv/bin/activate
        pip install -r requirements.txt
    - save_cache:
        key: v1-{{ checksum "requirements.txt" }}
        paths:
        - "venv"    # Download and cache dependencies
    

    安装 aws cli 到 python venv 环境

  4. 推送镜像到 aws ecr

    - run:
        name: Push Docker Image
        command: |
          . venv/bin/activate
          $(aws ecr get-login --no-include-email)
          docker tag mobingi-api-cn $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com.cn/mobingi-api-dev:$CIRCLE_SHA1
          docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com.cn/mobingi-api-dev:$CIRCLE_SHA1
    

    推送 docker 镜像到 aws ecr

    为了使 aws 能正常登陆,docker 镜像能正确 push 到 ecr,你需要在 CircleCI 当前项目中设置环境变量(设置方法)

    变量名称 变量值
    AWS_ACCOUNT_ID AWS_ACCOUNT_ID
    AWS_ACCESS_KEY_ID AWS_ACCESS_KEY_ID
    AWS_DEFAULT_REGION AWS CLI 默认使用的地区
    AWS_SECRET_ACCESS_KEY AWS_SECRET_ACCESS_KEY

更多 steps 信息请查看 官方文档

工作流 (workflows)

用于编排所有 job。假设您需要在特定分支或特定时间运行job,或者您希望某些 job 并行运行,而某些 job 依次运行。

在工作流配置中,使用工作流名称作为配置的键。工作流名称在当前配置文件中必须全局唯一。

下面是工作流使用的例子

workflows:
  version: 2
  nightly:
    triggers:
    - schedule:
        cron: "0 0 * * *"
        filters:
          branches:
            only:
            - master
            - beta
    jobs:
    - test

nightly 为工作流名称

schedule 可以指定工作流在指定时间工作

cron 使用POSIX定义crontab语法

filters->branches 过滤的分支

  • 任何符合only条件的分支都会运行该工作流
  • 任何符合ignore 条件的分支都不会运行该工作流
  • 如果未定义 onlyignore 则所有分支豆浆运行该工作流
  • 如果同时符合onlyignore 优先考虑 ignore

根据上面的介绍我们可以将我们前面的两个 job build 和 deploy 编排成一个工作流 (workflows) 并命名为:build-deploy

workflows:
  version: 2
  build-deploy:
    jobs:
    - build
    - deploy:
        requires:
        - build

更多信息请查看 官方文档

设置项目环境变量

因为有很多值不方便出现在 CircleCI 的配置文件中,例如一些密匙、服务 IP 等等。这时候我们就可以在 CircleCI 的管理面板中设置环境变量,然后在 job 获取这些变量。

1.在项目的的左上角,选择这个⚙️按钮

image.png

2.选择 Environment Variables -> Add Variable

在弹出的框中输入环境变量的 name 和 value 即可

使用 ssh 调试

当出现问题时,我们可能需要对问题进行调试,这时后我们可以 ssh 到 job 中对问题进行排查。

在出现问题的 job 右上角,在 Rebuild 下拉菜单中选择 Rebuild with SSH


image.png

稍等几分钟后

image.png

使用红圈中的命令即可使用 SSH 登陆当前 job 环境

SSH 将保持可用状态10分钟,然后自动关闭。

更多信息请查看 官方文档

本地测试 CircleCI 配置文件

  1. 创建个人API令牌 (dashboard->User Settings->Personal API Tokens->Create New Token)
  2. 设置环境变量 export CIRCLE_TOKEN=<你刚刚创建的 token>
  3. 收集以下信息:
  • 提交构建的哈希值
  • 用户名
  • 项目来源
  • 项目名
  • 从哪个分支建立
  1. .circleci 目录,创建 shell 脚本run-build-locally.sh 文件,文件内容为
#!/usr/bin/env bash
curl --user ${CIRCLE_TOKEN}: \
    --request POST \
    --form revision=<commit hash>\
    --form config=@config.yml \
    --form notify=false \
        https://circleci.com/api/v1.1/project/<source, eg. github>/<user name>/<project name>/tree/<branch name>

更多信息请查看 官方文档

其他资料

最终配置

CircleCI 官方入门简介

CircleCI 官方各种语言例子

CircleCI 官方配置说明

CircleCI官方例子 circleci-demo-aws-ecs-ecr

第三方参考例子 docker-circleci-ecr-ecs

参考文章

如何理解持续集成、持续交付、持续部署?

持续集成服务 Travis CI 教程

How CircleCI Works

How we used CircleCI 2.0 to build and deploy an Angular app to AWS S3

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,639评论 18 139
  • <<互联网敏捷DevOps和自动化之5.持续集成>>持续集成的价值是什么?对于开发和测试人员又意味着什么呢?1.1...
    燕京博士阅读 2,780评论 0 5
  • 本章是成本概念总结 成本概念深不可测 因为它是靠想象出来的,所以深不可测、千变万化。成本概念可以从具体到抽象、从个...
    爷有蔓草阅读 390评论 0 0
  • 前两天和妈妈处去遛弯,拍了很多照片,妈妈挑了其中一张照片说,我最喜欢这张,这张显得比较嫩。我说,妈妈,你看你...
    声声曼man阅读 1,123评论 7 6