美文网首页
github-actions部署koa实现CI/CD

github-actions部署koa实现CI/CD

作者: smallzip | 来源:发表于2021-12-22 16:40 被阅读0次

    背景

    一般公司的CI/CD流程相对来说较为专业、成熟且复杂,需要考虑通用性、安全性、可维护性等等,假如我们个人开发者也想要搞CI/CD,功能相对简单,使用的是github仓库,可以考虑github actions,接下来我就以一个koa的demo来实现CI/CD。

    目标

    我们要实现的流程包括,push之后将构建成为镜像,推送到docker hub中,服务器拉取docker hub最新镜像并在宿主机运行容器,钉钉能够监控CI/CD流程是否成功,并推送到钉钉群中。

    image-20211222095638878.png

    新建koa项目

    初始化kao

    初始一个空项目

    # 创建文件夹,名称为koa-demo
    mkdir koa-demo
    
    # 初始化一个package.json描述文件,描述这个NPM包的所有相关信息,包括作者、简介、包依赖、构建等信息
    npm init -y
    

    接下来安装koa,在终端输入命令

    npm install koa
    # 或者
    yarn add koa
    

    安装完毕后需要在根目录下创建一个index.js文件,来使用一下koa

    const Koa = require('koa');
    const app = new Koa();
    
    app.use(async ctx => {
      ctx.body = 'Hello World';
    });
    
    app.listen(3010);
    

    koa项目初始化完毕后,我们要跑起来看看,找到package.json,在scripts中新增命令行,命令为start,意思为启动项目,执行它会映射为执行node index.js,在node环境下执行index.js文件的代码,index.js就是我们上面创建的文件。

      "scripts": {
        "start": "node index.js"
      },
    

    验证项目是否成功,直接在终端输入

    npm start
    # 或者
    yarn start
    

    验证kao

    然后在浏览器访问:localhost:3010,浏览器看到hello world字样即为成功。

    img

    小结

    经过以上步骤,一个简单的koa项目创建完毕,并能够在本地运行正常运行起来,接下来需要将其打包构建成为一个镜像,最终成为容器运行起来。

    部署koa项目

    部署koa项目第一步需要先编写一个构建镜像的脚本文件。

    dockerfile

    我们的部署需要用到docker,首先需要在根目录下创建两个文件

    • Dockerfile
    • .dockerignore

    Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。Docker通过docker build执行Dockerfile中的一系列命令自动构建image镜像。

    .dockerignore就类似于git中的.gitignore在构建过程忽略的内容。

    Dockerfile文件需要写入以下内容

    # 制定node镜像的版本
    FROM node:17
    # 移动当前目录下面的文件到app目录下
    ADD . /app/
    # 进入到app目录下面,类似cd
    WORKDIR /app
    # 安装依赖
    RUN npm install
    # 对外暴露的端口,这里的3010需要和inde.js监听的端口一致
    EXPOSE 3010
    # 程序启动脚本,意思为 执行 npm start
    CMD ["npm", "start"]
    
    • FROM:构建所需要的镜像,就是一个定制化的过程,那么就需要以一个镜像为基础,在其基础上进行修改定制。而FROM指令就是用来指定基础镜像,因此在Dockerfile中,FROM指令是必备指定,并且必需是第一条指令!

    • ADD:当from的镜像拉取下面之后,可以将后续的文件内容都放到该镜像指定的目录位置,比如上面的将运行的koa项目放入到了node镜像下的/app/目录下。

    • RUN:构建镜像时执行的命令。RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache选项,如:docker build --no-cache

    • CMD:Docker不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,就需要指定运行的程序及参数。所以,CMD指令的主要用途是为启动容器时指定运行的程序及参数,而RUN指令用于指定镜像构建时所要执行的命令。

    .dockerignore文件写入一下内容,它的作用的过滤掉一些不必要的文件。

    # Logs
    logs
    *.log
    npm-debug.log*
    
    # Runtime data
    pids
    *.pid
    *.seed
    
    # Directory for instrumented libs generated by jscoverage/JSCover
    lib-cov
    
    # Coverage directory used by tools like istanbul
    coverage
    
    # nyc test coverage
    .nyc_output
    
    # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
    .grunt
    
    # node-waf configuration
    .lock-wscript
    
    # Compiled binary addons (http://nodejs.org/api/addons.html)
    build/Release
    
    # Dependency directories
    node_modules
    jspm_packages
    
    # Optional npm cache directory
    .npm
    
    # Optional REPL history
    .node_repl_history
    .idea
    .node_modules
    node_modules
    .vscode
    

    docker构建镜像

    我本机安装了docker桌面端,所以可以在本地测试。docker桌面端下载地址

    在项目根目录下,使用docker下的build命令构建镜像,-t为镜像的名字及标签

    docker build -t koa-demo .
    

    终端会输出下面内容

    [+] Building 4.3s (10/10) FINISHED                                                                                 
     => [internal] load build definition from Dockerfile                                                          0.0s
     => => transferring dockerfile: 301B                                                                          0.0s
     => [internal] load .dockerignore                                                                             0.0s
     => => transferring context: 661B                                                                             0.0s
     => [internal] load metadata for docker.io/library/node:17                                                    2.5s
     => [auth] library/node:pull token for registry-1.docker.io                                                   0.0s
     => [internal] load build context                                                                             0.0s
     => => transferring context: 1.12kB                                                                           0.0s
     => CACHED [1/4] FROM docker.io/library/node:17@sha256:13621aa823b6b92572d19c08a75f7b1a061633089f37873f8b5be  0.0s
     => [2/4] ADD . /app/                                                                                         0.0s
     => [3/4] WORKDIR /app                                                                                        0.0s
     => [4/4] RUN npm install                                                                                     1.6s
     => exporting to image                                                                                        0.1s
     => => exporting layers                                                                                       0.1s
     => => writing image sha256:c33e69d13b82487230b435ee7ae117b209d14a11631a57c57ec4dee9a92f5f5e                  0.0s
     => => naming to docker.io/library/koa-demo
    
    • 上面执行build会触发dockerfile文件,从docker中指定一个node版本,这里指定为最新的17版本,然后从docker仓库中拉取对应版本的node,其实是执行了docker pull node:17

    • 接下来将koa项目所有文件(不包括被忽略的文件)添加进/app/目录下

    • 接下来进入app目录内容,将app设置为工作目录

    • 接下来安装依赖

    以上就是dockerfile执行的所以流程了,那么我们如何运行起来呢,这个就是CMD命令做的事情了,CMD是负责指定运行的程序和参数。

    查看镜像

    先不着急启动,我们先看看镜像是否构建成功了。

    docker images
    
    image-2.png

    可以看到镜像的构建成功了的。

    运行镜像

    将镜像运行起来,会触发CMD命令,会将koa项目跑起来,并且我们要在浏览器中看到运行的koa输出内容。

    docker run -d -p 8888:3010 koa-demo
    
    • -d 是后台运行,不要阻塞shell指令窗口

    • -p 来制定内外端口映射

    • 8888 将内部端口和外部端口3010做一个简单的映射,这里是 外部端口:内部端口

    运行docker-demo镜像,并设置运行的内部端口为3010,因为koa设置的运行端口为3010所以要保持一致,8888是映射给容器外面的端口,即为用户访问的端口。

    查看容器

    docker ps
    
    image-3.png

    浏览器访问项目

    容器启动成功后,docker就启动了一个进程。

    在浏览器访问:http://localhost:8888

    image-4.png

    浏览器已经可以正常查看到运行的项目。

    小结

    编写了Dockerfile脚本文件,负责执行构建的流程,为了优化构建包.dockerignore大小忽略一下没必要的文件。

    通过执行docker build命令触发Dockerfile脚本生成了一个koa-demo镜像,执行docker run运行了一个容器,最后我们可以在浏览器中访问运行中的koa项目。

    github actions

    项目在本地docker环境能够正常运行,接下来开始用到github actions。

    使用github actions

    在github中,如果已经有项目的可以先把项目提交,若没有项目,直接新建一个项目,随后将本地修改后的代码提交上去。

    随后点击并打开Actions页面

    image-5.png

    会展示很多种构建类型,我们不用管它,只选择第一个,最简单的镜像构建就可以了。

    image-6.png

    选择第一个docker镜像后,会生成一些代码

    image-7.png

    镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,我们公司内部使用的是私有仓库,这里我们使用Docker Hub共有仓库即可。

    因为我们需要将docker镜像构建完毕后推送到Docker Hub中,所以需要新增一个镜像推送,需要用到Docker Hub的账户和密码,需要去注册一下,点我去注册

    docker-image.yml需要做一些简单的修改,内容如下:

    name: Docker Image CI
    
    on:
      push:
        branches: [main]
      pull_request:
        branches: [main]
    
    jobs:
      build:
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v2
          - name: Build the Docker image
            uses: elgohr/Publish-Docker-Github-Action@master
            with:
              name: smallzip7799/koa-github-action
              username: ${{ secrets.DOCKER_USERNAME }}
              password: ${{ secrets.DOCKER_PASSWORD }}
    

    为了更好的理解,来讲解一下每一行的含义

    • line1:actions工作流的名称。

    • line3~7:当我们用main分支,将代码推送(push或者pull_request)到仓库的时候,会触发我们的工作流程(workflow)。

    • line8~11:我们定义了一个workflow工作流,由一个或者多个jobs构成,能一次持续集成的运行,完成多个任务。后面的每个工作流都在虚拟环境的新实例中运行,其中的runs-on字段指定运行所需要的虚拟环境。

    • line13steps指定每一个job的运行步骤,可以包含一个或者多个步骤。

    • line14:使用github提供的actions/checkout@v2,它的作用就是让我们的workflow可以访问到repo源码的内容。

    • line15:第二个步骤的名称,可以根据实际情况写个步骤简要描述,它会显示在构建流程中

    • line16:使用用户名为elgohr定制的Publish-Docker-Github-Action@master钩子执行docker镜像的构建和推送流程,最终推送到docker hub中。

    • line17~20:这里定义推送的docker hub所需要的参数

      • name:是推送到docker hub的镜像名称
      • username:registry的登录用户名,即为docker hub的用户名
      • password:registry的登录密码,即为docker hub的密码

    其中的usernamepasword是属于私密内容,不应该直接显示在代码中,因此我们需要在github 的secrets设置一下,将usernamepassword设置为局部变量。

    image-8.png

    写完代码后,直接提交,第一次会执行一次构建流程。

    image-9.png

    显示打钩则代表构建成功了。

    详细的pipeline流程,可以点击进去查看详情。

    image-10.png

    检查镜像

    推送代码后,我们可以通过在docker hub里面检查已经构建成功的镜像。

    image.png

    又或者在本机docker桌面端中查看

    image.png

    部署到服务器

    当前构建过程中,只包含了镜像的构建,并推送到docker hub公共仓库,还没有做到在服务器中的部署流程。这些操作需要使用到:

    • 一个个人服务器
    • 服务器中启动openssh-server

    如果有个人服务器可以直接看下一步,如果没有服务器,可以去腾讯云、阿里云、华为云这些平台购买一个便宜的服务器用来学习,这里推荐不到25岁的小伙伴们,去腾讯云购买学生服务器,一年只需要108rmb,购买地址

    购买好服务器,第一步是安装好openssh-server,第二步是安装好docker环境,由于我购买的是CentOS7.6,不同服务器安装方式不太一样,具体安装教程参见官网

    新增部署流程

    github actions默认生成的workflow工作流只包含了镜像推送,要实现服务器的部署和钉钉推送需要再新增两个工作流

    name: Docker Image CI
    
    on:
      push:
        branches: [main]
      pull_request:
        branches: [main]
    
    jobs:
      build:
        runs-on: ubuntu-latest
    
        steps:
          - uses: actions/checkout@v2
          - name: Build the Docker image
            uses: elgohr/Publish-Docker-Github-Action@master
            with:
              name: smallzip7799/koa-github-action
              username: ${{ secrets.DOCKER_USERNAME }}
              password: ${{ secrets.DOCKER_PASSWORD }}
    
          # 部署服务器
          - name: executing remote ssh commands using password
            uses: appleboy/ssh-action@master
            with:
              host: ${{ secrets.HOST }}
              username: ${{ secrets.USERNAME }}
              password: ${{ secrets.PASSWORD }}
              port: 22
              script: |
                docker pull smallzip7799/koa-github-action
                docker inspect -f '{{.Name}}' koa-docker
                if [ $? == 0 ] ;then
                  echo "docker exist"
                  docker container stop koa-docker
                  docker container rm koa-docker
                  docker images remove smallzip7799/koa-github-action
                else
                  echo "docker don't exist"
                fi
                docker run -d -p 8888:3010 --name koa-docker smallzip7799/koa-github-action
    
          # 发送钉钉消息
          - name: dingtalk robot message
            uses: fifsky/dingtalk-action@master
            with:
              url: ${{ secrets.DINGTALK_WEBHOOK}}
              type: markdown
              content: |
                ## 监控提示:💯👨💻 Success 🎉🎉🎉
                  构建成功了
    
    

    为了都能理解,这里解释新增的两个工作流:

    • line32executing remote ssh commands using password是当前工作流的名称或者描述,可以自己修改。
    • line24:这里使用了第三方用户封装好的actions钩子,它的作用是通过ssh登录远程服务器。(持续集成由很多操作组成,比如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等。GitHub 把这些操作就称为 actions,如果需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,actions仓库)。
    • line25with表示actions拥有参数。
    • line26~line29host是服务器公网的ip地址,usernamepassword分别是docker注册是账户名和密码,post是ssh访问端口,默认为22。其中hostusernamepassword建议使用局部变量,不要直接现实在代码中。
    • line30~line41:执行shell命令
      • docker pull smallzip7799/koa-github-actions:拉取docker hub上面的镜像
      • docker inspect -f '{{.Name}}' koa-docker:检查是否存在名字为koa-docker的容器
      • if [ $? == 0 ] ;then$?是代表上一条命令的返回值,判断是否存在
      • docker container stop koa-docker:将koa-docker容器暂停
      • docker container rm koa-docker:删除koa-docker容器
      • docker run -d -p 8888:3010 --name koa-docker smallzip7799/koa-github-action:运行镜像,设置对外端口8888,映射到内部端口3010,设置容器的名称为koa-docker
    • line43dingtalk robot message工作流名称
    • line44fifsky/dingtalk-action@master,使用钉钉消息通知actions
    • line46~line50url为钉钉配置的webhooktypemarkdown,内容中包括了钉钉通知配置的关键词和内容。参见钉钉机器人

    重新构建

    修改完毕后,提交代码,等待github actions工作流完成,如果顺利将会在钉钉收到通知

    image.png

    打开浏览器输入服务器IP地址+端口号,会看到

    image.png

    以上即为github actions实现的koa项目CI/CD。

    小结

    使用ssh远程到服务器,并在服务器中执行docker拉取和运行的命令,将项目运行起来。

    利用钉钉群中的机器人生成webhook钩子,实现消息群通知。

    总结

    github actions部署koa项目最核心的地方是编写workflow工作流,工作流中可以做非常多的操作,如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等,当一些操作相对复杂或者具有相似性,可以直接引用他人写好的 action,亦或自己写run命令。

    当前项目是基于node运行环境,若项目为静态文件,比如vue项目、react项目则需要使用其他的运行环境,如nginx等,原因是vue、react会打包成dist或者build可运行文件,将其运行不需要使用到进程服务,可以直接在浏览器访问,因此只需要将其放置到代理服务器中,将访问文件地址暴露给外网访问即可。

    参考文献

    相关文章

      网友评论

          本文标题:github-actions部署koa实现CI/CD

          本文链接:https://www.haomeiwen.com/subject/rsgqqrtx.html