一、什么是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 CI 、Jenkins 、Docker 、Kubernetes。 |
Windows 环境 | CI/CD 工具也支持在 Windows 系统上运行,可能需要通过 Docker 或 WSL 模拟 Linux 环境。 | 支持 :GitHub Actions 、Jenkins (通过 WSL 或 Docker)、Docker for Windows。 |
macOS 环境 | macOS 用户可以运行 CI/CD 工具和 Docker,通常依赖 Docker 来模拟 Linux 环境。 | 支持 :GitHub Actions 、GitLab CI 、Docker Desktop 、Jenkins。 |
云环境 | CI/CD 服务提供商如 GitHub Actions 和 GitLab CI 提供云端执行环境,通常运行在 Linux 中。 | 支持 :GitLab CI/CD 、GitHub Actions 、CircleCI 等云平台。 |
执行工具示例 | 需要特定的 CI/CD 工具来解析和执行 YAML 文件中的配置。 | GitLab CI 、GitHub Actions 、Jenkins 、CircleCI 、Travis 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镜像
三、阿里云➕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)"
(三)更新分支代码验证



