前端部署-CICD

一、什么是CICD

CICD 是 Continuous Integration (持续集成)和 Continuous Delivery (持续交付)或 Continuous Deployment(持续部署)的缩写。它是一套现代软件开发方法,用于自动化软件开发过程中的构建、测试、发布等环节,从而提高开发效率、减少人为错误,并确保软件始终处于可交付状态。

1. 持续集成(CI)

持续集成的核心理念是开发人员频繁地(通常是每天多次)将代码集成到共享的代码库中。在每次代码提交后,CI 工具会自动执行以下步骤:

  • 自动化构建:对代码进行编译和构建。
  • 自动化测试:执行单元测试、集成测试等,以确保新提交的代码不会破坏现有功能。
  • 代码质量检查:比如静态代码分析、代码覆盖率检查等。

目的是及时发现和解决问题,避免积压大量的错误和技术债务。

2. 持续交付(CD)

持续交付指的是将持续集成的成果(通过自动化构建和测试的代码)自动部署到一个与生产环境相似的环境中。通过自动化的方式,确保代码随时可以部署到生产环境,只需要一次手动操作就能推送到生产。持续交付的目的是确保软件交付的速度更快、质量更高,同时能够在任意时刻发布软件。

3. 持续部署(CD)

持续部署是持续交付的进一步延伸,指的是自动化将通过测试的代码自动部署到生产环境中。每次代码提交通过所有的测试后,系统会立即将新版本的应用程序部署到生产环境,而无需人工干预。这样开发团队可以更频繁地发布新功能或修复bug。

4、CICD 的好处:

  • 提高开发效率:自动化构建和测试减少了手动操作,提高了开发人员的工作效率。
  • 快速发现问题:通过持续集成和自动化测试,能在早期发现代码中的问题,减少了bug的积压。
  • 稳定的发布流程:确保每次发布都是经过充分测试的,降低了生产环境出错的风险。
  • 更频繁的发布:团队可以更快速地推出新功能或修复bug,缩短产品的迭代周期。

提交代码 -> 检测变化 -> 生成镜像 -> 自动部署镜像

二、基础了解

1、yaml

一个按照特定语法实现的可以顺序执行的一种特殊的数据结构文件。通常用于编写CICD的整个自动化过程的一个执行文件。

yaml文件可以运行的环境:

项目 说明 支持的操作系统/环境
YAML 文件 一种平台无关的数据格式,用于配置和数据交换。 跨平台,可以在 Linux、Windows、macOS 等环境中使用。
执行环境 YAML 文件的执行依赖于 CI/CD 工具应用程序 依赖于 CI/CD 工具,支持多平台:Linux、Windows、macOS。
Linux 环境 大多数 CI/CD 工具运行在 Linux 系统上,尤其是在容器化环境中。 支持 :大部分 CI/CD 工具,如 GitLab CIJenkinsDockerKubernetes
Windows 环境 CI/CD 工具也支持在 Windows 系统上运行,可能需要通过 Docker 或 WSL 模拟 Linux 环境。 支持GitHub ActionsJenkins (通过 WSL 或 Docker)、Docker for Windows
macOS 环境 macOS 用户可以运行 CI/CD 工具和 Docker,通常依赖 Docker 来模拟 Linux 环境。 支持GitHub ActionsGitLab CIDocker DesktopJenkins
云环境 CI/CD 服务提供商如 GitHub Actions 和 GitLab CI 提供云端执行环境,通常运行在 Linux 中。 支持GitLab CI/CDGitHub ActionsCircleCI 等云平台。
执行工具示例 需要特定的 CI/CD 工具来解析和执行 YAML 文件中的配置。 GitLab CIGitHub ActionsJenkinsCircleCITravis CI 等。
操作系统依赖 YAML 文件本身不依赖操作系统,取决于工具的执行环境。 跨平台 ,取决于 CI/CD 工具,可以是 Linux、Windows 或 macOS。

2、基础的语法和示例

参考博客:www.ruanyifeng.com/blog/2016/0...

示例文件:

yaml 复制代码
# 定义 CI/CD 阶段
stages:
  - install
  - build
  - deploy

# 安装 Node.js 和依赖
install_job:
  stage: install  # 设置阶段为安装
  image: node:16  # 使用 Node.js 官方镜像,指定版本为 16
  # 运行脚本命令
  script:
    # 1. 安装 Node.js 的依赖
    - echo "安装 Node.js 依赖..."
    - npm install  # 安装项目的 Node.js 依赖
    # 2. 安装 Docker(如果 CI 环境中没有 Docker)
    - echo "安装 Docker..."
    - apt-get update && apt-get install -y docker.io  # 安装 Docker
    - docker --version  # 确认 Docker 安装成功

# 运行 shell 脚本(比如执行部署或配置脚本)
run_sh_script_job:
  stage: build  # 设置阶段为构建
  script:
    # 3. 运行自定义的 shell 脚本文件
    - echo "运行 shell 脚本 deploy.sh..."
    # ./deploy.sh : 指的是文件仓库的根目录
    - chmod +x ./deploy.sh  # 给 deploy.sh 脚本加上执行权限
    - ./deploy.sh  # 执行脚本

# 项目打包
build_job:
  stage: build  # 设置阶段为构建
  script:
    # 4. 打包 Node.js 项目
    - echo "打包项目..."
    - npm run build  # 运行项目的构建命令(例如打包)
    - echo "打包完成!"

# 部署到 Docker 容器中
deploy_docker_job:
  stage: deploy  # 设置阶段为部署
  script:
    # 5. 构建 Docker 镜像
    - echo "构建 Docker 镜像..."
    - docker build -t my-app-image .  # 使用 Dockerfile 构建镜像
    # 6. 运行 Docker 容器
    - echo "运行 Docker 容器..."
    - docker run -d -p 8080:80 my-app-image  # 在后台运行 Docker 容器,映射端口

2、docker镜像

官网:www.dockerdocs.cn/

参考博客:juejin.cn/post/752525...

三、阿里云➕GitHub 实现CICD自动部署

1、阿里云准备工作

1-1、 创建阿里云个人版镜像仓库

help.aliyun.com/zh/acr/user...

1-2、查验并验证镜像仓库

按照官方示例,登录自己的阿里云服务器进行验证

2、GitHub配置

2.1、设置 Actions

2.2、设置可以在yaml文件中读取的环境变量

2.3、编写yaml文件

(一)文件创建

方案一:本地代码仓库自定义创建

项目根目录创建 .github 文件夹 .github 文件夹下创建 main.yml文件【文件名自定义,尽量和分支保持一致】

方案二:在线编辑

(二)yml 文件编写

yml运行的环境是 github服务环境一切的操作和你的阿里云服务器没有关联

我们可以通过使用工具和脚本去和我们的阿里云服务作关联

yml 复制代码
# action名称
name: dev-cicd
# 监听的分支:                
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
# 设置文件全局变量
env:
  REPO_TAG: "fe-dev"
# 设定运行步骤
jobs:
  # 运行步骤配置
  build:
    # 运行环境
    runs-on: ubuntu-latest
    # 运行步骤
    steps:
    #  安装Node.js
      # First, check out your repository 【一定要有!!!】
    - name: Checkout repository
      uses: actions/checkout@v4
      # 选择node版本
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '20'
      # 运行打包脚本
    - name: Run build script
      run: npm install && npm run build  
      # 制作镜像
    # docker build
    - name: Build Docker image
      run: docker build . --file dockerFile --tag ${{env.REPO_TAG}}
    # docker 镜像推送仓库 
    # ${{secrets.USER_NAME}} 就是设置的环境变量
    # 登录阿里云镜像仓库
    - name: login Registry
      run: docker login -u=${{secrets.USER_NAME}} -p=${{secrets.PASS_WORD}} crpi-muyq5tde0d12r3tr.cn-beijing.personal.cr.aliyuncs.com
    # 设置镜像TAG
    - name: tag Image
      run: docker tag ${{env.REPO_TAG}} crpi-muyq5tde0d12r3tr.cn-beijing.personal.cr.aliyuncs.com/my_ljx_test/dev:${{env.REPO_TAG}}
    # 推送镜像到阿里云镜像仓库
    - name: docker Push 
      run: docker push crpi-muyq5tde0d12r3tr.cn-beijing.personal.cr.aliyuncs.com/my_ljx_test/dev:${{env.REPO_TAG}}
    # 登陆服务器使用脚本自动替换镜像,使用最新推送的镜像
    - name: Deploy to Aliyun Server
      uses: appleboy/ssh-action@v1.0.0
    # 链接阿里云服务器【该命令后所有的操作均在个人阿里云服务环境!!】
      with:
        host: ${{ secrets.SSHADDRESS }}
        username: 'root'
        password: ${{ secrets.SSHPASSWORD }}
        port: 22
        script: |
          set -e  # 遇到错误时停止执行
          
          echo "=== 开始部署 ==="
          echo "时间: $(date)"
                   
          # 登录阿里云容器镜像服务
          echo "=== 登录阿里云镜像仓库 ==="
          docker login -u=${{secrets.USER_NAME}} -p=${{secrets.PASS_WORD}} crpi-muyq5tde0d12r3tr.cn-beijing.personal.cr.aliyuncs.com
          # 拉取最新镜像
          echo "=== 拉取最新镜像 ==="
          docker pull crpi-muyq5tde0d12r3tr.cn-beijing.personal.cr.aliyuncs.com/my_ljx_test/dev:${{env.REPO_TAG}}
          # 停止并删除旧容器
          echo "=== 停止旧容器 ==="
          if docker ps -q --filter "name=${{ env.REPO_TAG }}" | grep -q .; then
            docker stop ${{ env.REPO_TAG }}
            echo "容器已停止"
          fi
          
          if docker ps -aq --filter "name=${{ env.REPO_TAG }}" | grep -q .; then
            docker rm ${{ env.REPO_TAG }}
            echo "容器已删除"
          fi
          
          # 启动新容器
          echo "=== 启动新容器 ==="
          docker run -d \
            -p 8080:80 \
            --name ${{ env.REPO_TAG }} \
            crpi-muyq5tde0d12r3tr.cn-beijing.personal.cr.aliyuncs.com/my_ljx_test/dev:${{ env.REPO_TAG }}
          
          # 等待容器启动
          echo "=== 等待容器启动 ==="
          sleep 10
          
          # 检查容器状态
          echo "=== 检查容器状态 ==="
          if docker ps --filter "name=${{ env.REPO_TAG }}" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -q "${{ env.REPO_TAG }}"; then
            echo "✅ 容器启动成功"
            docker ps --filter "name=${{ env.REPO_TAG }}" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
          else
            echo "❌ 容器启动失败"
            docker logs ${{ env.REPO_TAG }} --tail 50
            exit 1
          fi          
          echo "=== 部署完成 ==="
          echo "时间: $(date)"
      
(三)更新分支代码验证
相关推荐
小小小小宇1 分钟前
重提Vue 3 性能提升
前端
eason_fan2 分钟前
React 源码执行流程
前端·源码阅读
will_we25 分钟前
服务器主动推送之SSE (Server-Sent Events)探讨
前端·后端
yume_sibai34 分钟前
Less Less基础
前端·css·less
小小小小宇34 分钟前
重提Vue3 的 Diff 算法
前端
清岚_lxn35 分钟前
前端js通过a标签直接预览pdf文件,弹出下载页面问题
前端·javascript·pdf
不爱说话郭德纲1 小时前
别再花冤枉钱!手把手教你免费生成iOS证书(.p12) + 打包IPA(超详细)
前端·ios·app
代码的余温1 小时前
Vue多请求并行处理实战指南
前端·javascript·vue.js
余杭子曰2 小时前
组件设计模式:聪明组件还是傻瓜组件?
前端
杨超越luckly2 小时前
HTML应用指南:利用GET请求获取全国小米之家门店位置信息
前端·arcgis·html·数据可视化·shp