githubActionCICD实战
# github action CI/CD 实战
# 什么是ci
持续集成,需要用户主动提交代码,触发代码集成、自动化构建、自动化测试流程
# 什么是cd
持续交付、持续部署,不需要用户干预,自动将ci准备好的构建文件发布到生产环境
# ci/cd的工具介绍
DeepSeek-R1满血版 思考完成
好的,用户现在需要介绍CI/CD工具。首先,我需要回顾之前的对话历史,确保不重复之前的内容。用户之前已经询问过CI/CD的简介和相关图片,现在具体想了解工具。根据提供的搜索结果,有很多工具被提到,比如Jenkins、GitLab CI、Travis CI、Ansible、Kubernetes等。需要将这些工具分类整理,并按照不同的功能模块来介绍。
# 一、持续集成(CI)工具
Jenkins
特点:开源、插件生态丰富,支持与 Git、Maven 等工具深度集成,可通过配置流水线实现自动化构建、测试和部署。 适用场景:企业级复杂项目,需高度定制化的 CI/CD 流程。
GitLab CI
特点:与 GitLab 代码仓库无缝集成,通过 .gitlab-ci.yml 文件定义流水线,支持容器化构建和并行任务。 适用场景:团队协作开发,尤其是 GitLab 托管项目。
Travis CI
特点:云端服务,深度支持 GitHub 项目,配置简单,适用于开源项目和小型团队。 限制:免费版对私有仓库的支持有限。
Apache BuildStream
特点:基于 YAML 文件定义构建流程,通过哈希缓存机制加速构建,适合管理复杂软件组件的依赖关系。 二、持续交付/部署(CD)工具
Ansible
特点:无代理架构,通过 YAML 编写 Playbook 实现配置管理和自动化部署,支持多云环境。 优势:轻量级且易于扩展,适合中小规模基础设施。
AWS CodeDeploy
特点:与 AWS 云服务深度集成,支持蓝绿部署和滚动更新,可自动监控部署状态。 适用场景:基于 AWS 的云原生应用部署。
Kubernetes
特点:容器编排工具,支持声明式部署和自动扩缩容,与 Helm 等工具结合可实现应用版本管理。 核心价值:提升容器化应用的部署效率和稳定性。
# github action介绍
github actions实验室 (opens new window)
Github在2019年底开放了内置的CI/CD工具GithubActions
.这样使用Github托管的代码终于有了不借助外部服务自动化测试打包部署的能力. 同时由于后发优势,GithubActions
几乎是目前最易用的CI/CD工具.
GithubActions类似于传统的CI/CD工具,都是使用代码配置脚本,执行器执行脚本,页面管理执行过程的结构.
- 在代码中配置脚本放在根目录的.github/workflow文件夹下,使用yaml格式描述配置.
- Github默认给每个用户配置3个的执行器,我们也可以自己创建self-host执行器
- 每个代码仓库的顶部标签页都有专门的actions按钮,进去就是当前仓库的执行过程管理页面.
- 代码提交到
github
仓库, - 触发
push
事件 - 工作流开始工作,顺序执行
job
,job
在runner
上执行 job
中step
也是顺序执行的,step
可以是actions
或者command
- 工作流完成,会生成一份报告
# 为什么我选择github action
无需额外的服务器资源,个人使用足够了
500mb的存储,每月2000分钟的免费使用时间,同时可以运行20个工作流,对于个人使用足够了
# 利用github Action 实现个人服务器的CI/CD
因为考虑到以后会有多个项目都需要打包部署,这里考虑使用配置文件来集中管理需要打包编译的项目。
{
"images": [
{
"name": "playwright-go",
"tag": "1.24",
"dockerfile": "playwright/go/Dockerfile"
},
{
"name": "maven3.5-jdk8",
"tag": "latest",
"dockerfile": "maven/Dockerfile"
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
这里的images是一个数组,每个元素都是一个对象,对象中包含了name、tag、dockerfile三个属性,分别表示镜像名称、镜像版本、dockerfile路径。
然后解决编译问题,我一般直接采用docker部署的方式,这样可以避免环境问题,同时也可以减少编译时间,因为docker镜像已经包含了编译环境,这里涉及到一个新知识strategy.matrix
矩阵策略允许用户在一个工作流中定义多个变量组合,这样可以同时运行多个作业,每个作业使用不同的配置。一般可以用做同一套代码在不同环境下的测试,比如linux、windows、macOS等。
这里我们用作准备不同的镜像文件在相同的环境下进行编译
needs: prepare
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Read image config
id: read_config
run: echo "config=$(cat .github/docker-images.json | jq -c)" >> $GITHUB_OUTPUT
2
3
4
5
6
7
8
9
10
11
12
13
14
读取好变量进行编译打包操作
- name: Build images
run: |
# 检查Dockerfile是否存在
if [ ! -f "${{ matrix.dockerfile }}" ]; then
echo "错误: Dockerfile不存在: ${{ matrix.dockerfile }}"
exit 1
fi
echo "开始构建镜像: ${{ matrix.name }}:${{ matrix.tag }}"
# 构建Docker镜像
docker build -t ${{ matrix.name }}:${{ matrix.tag }} -f ${{ matrix.dockerfile }} .
# 检查构建结果
if [ $? -ne 0 ]; then
echo "错误: 镜像构建失败"
exit 1
fi
echo "镜像构建成功,检查镜像是否存在"
# 验证镜像是否存在
docker images | grep "${{ matrix.name }}" | grep "${{ matrix.tag }}"
echo "开始保存镜像为tar文件"
# 将镜像保存为tar文件
docker save ${{ matrix.name }}:${{ matrix.tag }} > /tmp/${{ matrix.name }}_${{ matrix.tag }}.tar
# 检查保存结果
if [ $? -ne 0 ]; then
echo "错误: 保存镜像失败"
exit 1
fi
echo "检查tar文件是否存在"
# 验证tar文件是否存在
ls -la /tmp/${{ matrix.name }}_${{ matrix.tag }}.tar
echo "镜像构建和保存完成"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
这里将打包好的文件存入/tmp目录下,再使用actions/upload-artifact@v4
action工具,将打包好的tar包上传到github服务器上,这样就可以在后续的步骤中使用这个tar包进行部署操作了。工具的逻辑已经实现好了,只需要配置文件名称,文件地址即可
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}_${{ matrix.tag }}
path: /tmp/${{ matrix.name }}_${{ matrix.tag }}.tar
overwrite: true
if-no-files-found: error # 如果找不到文件则报错
retention-days: 1
2
3
4
5
6
7
8
9
然后到了CD步骤,将打包好的tar包下载下来,无论是进行镜像推送还是服务器部署,都可以使用这个tar包进行操作,这样就实现了一个完整的CI/CD流程。
push-to-dockerhub:
needs: [prepare, build]
runs-on: ubuntu-latest
strategy:
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
steps:
- name: Download image artifact
uses: actions/download-artifact@v4
with:
name: ${{ matrix.name }}_${{ matrix.tag }}
path: /tmp
- name: Load Docker image
run: |
ls -la /tmp
docker load --input /tmp/${{ matrix.name }}_${{ matrix.tag }}.tar
docker tag ${{ matrix.name }}:${{ matrix.tag }} ${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.name }}:${{ matrix.tag }}
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
registry: docker.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Push to DockerHub
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.name }}:${{ matrix.tag }}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
这里因为只是基础镜像的构建,所以我没有加入部署操作,如果需要远程部署的话可以使用工具appleboy/ssh-action@master
,这个工具可以实现远程服务器的部署操作,具体的使用方法如下
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
script: |
docker login -u ${{ secrets.ALIYUN_USERNAME }} -p ${{ secrets.ALIYUN_PASSWORD }} ${{ env.REGISTRY }}
docker pull ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:latest
docker stop {{env.CONTIANER_NAME}} || true
docker rm {{env.CONTIANER_NAME}} || true
docker run -d \
--name {{env.CONTIANER_NAME}} \
--restart always \
-p 8080:8080 \
${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}:latest
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
这样就实现了一个完整的CI/CD流程,这里只是一个简单的例子,如果需要自己使用并且改造的话,可以参考我的github仓库 (opens new window)