随笔

Github CI/CD + Self Hosted Docker

最近学习时看到 CI/CD,前面几份工作很少接触到,因为都是运维的活,甚至自己搞的发布系统,也没机会接触,所以就拿 Github 浅浅尝试配置下吧。

Why

CI 全称 Continuous integration,顾名思义“持续集成”,核心在于集成,一个团队每时每刻都可能有人在提交代码,而怎样可以快速发现可能出现的错误,就在于每次提交后自动进行集成结果测试。

CD 全称 Continuous delivery 持续交付,Continuous deploy 持续部署,其核心在于可以随时交付出一个可以部署的东西,比如使用 Docker 打包出某个版本的镜像后,这个镜像可以随时随地拿去部署使用。

所以使用原因很明显,及时发现问题,随时可以一键部署或者回滚。

Github CI/CD

有很多系统可以做,甚至自己手工写也可以搞这些,目前较流行的是 Jenkins,并且它是免费的,除此之外就 Github 还有 Gitlab 都可以做,因为本身就是代码库,集成起来肯定更方便,总之根据状况选择即可。

CI

mkdir .github/workflows

name: CI

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:
  build:
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js
        uses: actions/setup-node@v3.4.1
        with:
          node-version: "18.x"

      - name: Run build
        run: |
          cd management-system-react
          npm install
          npm run build

首先,我们来一个 CI 测试下,配置文件是 yaml 格式,看上去是不是很简单?而且一眼就能看出每行的作用,比如 on 很明显就是什么时候触发,关键词和语法可以去文档里查询。

用语言描述就是:“在 master 分支有 push 或者 pull_request 时触发,然后执行一个叫 build 的工作,build 中首先 checkout 代码,然后安装 node v18 环境,最后根据提供的命令行执行 build”。

1.png

保存并提交后 workflow 就会自动运行,绿色代表运行成功。

2.png

3.png

点进去可以看到执行了那些步骤,每个步骤是否成功。

CD

上面只 build 但是并没有保存和部署,所以现在来做这些操作,可以通过 Github 界面上的 Create 尝试下,内部预定义好了很多平台的配置方法,比如微软云,阿里云,亚马逊云等云服务商。

这次我要做的是另一种,基于本地或者说自有服务器的构建部署。

4.png

首先来到项目下的 settings -> actions -> runners,点击 New 有文档告诉你如何增加自己的 runner,我这里已经加好了一个具有四个 tag 的 runner,后续使用可根据 tag 匹配 runner 使用。

我们这次的最终目的是一个 React 项目提交代码后,自动触发打包并且部署好。共需要创建三个文件:

  1. Github 的 workflow 配置文件
  2. Dockerfile
  3. nginx.conf

docker.yaml

name: Self Hosted Docker

on:
  push:
    branches: ["test-runner"]
  workflow_dispatch:

jobs:
  build:
    runs-on: [self-hosted, docker]
    defaults:
      run:
        working-directory: ./management-system-react
    steps:
      - uses: actions/checkout@v3
      - name: Get commit tag
        run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV
      - name: Build
        run: docker build -t frontend:${{ env.SHORT_SHA }} .
  deploy:
    needs: build
    runs-on: [self-hosted, docker]
    defaults:
      run:
        working-directory: ./management-system-react
    steps:
      - name: Get commit tag
        run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV
      - name: Stop old container
        continue-on-error: true
        run: |
          docker stop $(docker ps --filter name=frontend -q)
          docker rm frontend-${{ env.SHORT_SHA }}
      - name: Deploy
        run: docker run --name frontend-${{ env.SHORT_SHA }} -d -p 80:80 frontend:${{ env.SHORT_SHA }}

Dockerfile

FROM node:18-alpine as builder

WORKDIR /app
COPY package.json .

RUN npm config set registry http://registry.npm.taobao.org
RUN npm install
COPY . .
# Because Error: The service was stopped
# https://github.com/vitejs/vite/issues/876#issuecomment-824557144
RUN node node_modules/esbuild/install.js
RUN npm run build

FROM nginx:1.23-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html

nginx.conf

server {
    listen       80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        try_files $uri $uri/index.html /index.html;
    }
}

通过 Github Action 触发 workflow,workflow 分为两个 job

  • build job 使用 git commit 的 sha 打包镜像
  • deploy job 停掉旧的运行容器,并启动新的容器

5.png

6.png

7.png

以上是一次完整的流程,发布后线上忽然出现了一个紧急 BUG,需要立刻会滚,那么可以通过点击需要会滚到的版本,点击 deploy 的 re-run 即可。

8.png

如图中最新版 #31e403 忽然发现 BUG 需要回滚,进入前一个正常版本 #a9169629 的 deploy job 点击运行,然后运行的容器就自动回滚到 #a9169629,并且是不需要重新执行 build 动作的,因为之前已经 build 过了。

9.png

10.png

Reference

本文链接:https://note.lilonghe.net/post/ci-and-cd-first-try.html

-- EOF --