当前位置: 首页 > news >正文

持续集成指南:GitHubAction 自动构建+部署AspNetCore项目

前言

之前研究了使用 GitHub Action 自动构建和发布 nuget 包:开发现代化的.NetCore控制台程序:(4)使用GithubAction自动构建以及发布nuget包

现在更进一步,使用 GitHub Action 在其提供的 runner 里构建 docker 镜像,之后提交到阿里云镜像私有仓库,再在本地的 runner 将镜像 pull 下来运行。

本文以 AIHub 项目为例。

AIHub 是一个集成多种模型的AI平台,提供了大模型、计算机视觉、自然语言处理等多种功能,基于 AspNetCore + Blazor Server 技术开发。

准备 Dockerfile

首先准备好构建镜像的 Dockerfile

一般来说使用 dotnet cli 创建项目的时候可以自动生成这个 Dockerfile

没有的话可以参考我这个

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["AIHub.Blazor/AIHub.Blazor.csproj", "AIHub.Blazor/"]
RUN dotnet restore "AIHub.Blazor/AIHub.Blazor.csproj"
COPY . .
WORKDIR "/src/AIHub.Blazor"
RUN dotnet build "AIHub.Blazor.csproj" -c Release -o /app/buildFROM build AS publish
RUN dotnet publish "AIHub.Blazor.csproj" -c Release -o /app/publish /p:UseAppHost=falseFROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AIHub.Blazor.dll"]

可以先在本地试一下 build 有没有问题

docker build .

一切正常可以进入下一步

创建私有镜像仓库

可以自行搭建,也可以使用云服务产品,我这里使用阿里云的「容器镜像服务 ACR」,个人版是免费的。

创建一个镜像仓库,代码源选择「本地仓库」,可以通过命令行推送镜像到镜像仓库。

PS: 我看里面还有 GitHub 仓库作为代码源,不过我还没测试。

创建之后有个操作指南,这不是很重要,我们只需要关注用户名和密码就行。

用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。

可以在访问凭证页面修改凭证密码。

OK,这些信息保存好,接下来需要用到。

本文使用的仓库地址是: registry.cn-hangzhou.aliyuncs.com/deali/aihub-test

配置 GitHub Action Secret

将阿里云仓库的地址、用户名、密码等信息配置到 Action Secret 中

这里我设置的名字是

  • ALIYUN_DOCKER_REPO

  • ALIYUN_USERNAME

  • ALIYUN_PWD

构建镜像

编写 GitHub workflow 配置,细节不再赘述,不清楚的同学可以参考这篇文章: 开发现代化的.NetCore控制台程序:(4)使用GithubAction自动构建以及发布nuget包

GitHub 提供的 workflow

这是 GitHub 提供的,我没有使用这个方案,有兴趣的同学可以自行尝试一下。

# 此工作流使用未经 GitHub 认证的操作。
# 它们由第三方提供,并受
# 单独的服务条款、隐私政策和支持
# 文档。# GitHub 建议将操作固定到提交 SHA。
# 若要获取较新版本,需要更新 SHA。
# 还可以引用标记或分支,但该操作可能会更改而不发出警告。name: Publish Docker imageon:release:types: [published]jobs:push_to_registry:name: Push Docker image to Docker Hubruns-on: ubuntu-lateststeps:- name: Check out the repouses: actions/checkout@v4- name: Log in to Docker Hubuses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20awith:username: ${{ secrets.DOCKER_USERNAME }}password: ${{ secrets.DOCKER_PASSWORD }}- name: Extract metadata (tags, labels) for Dockerid: metauses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7with:images: my-docker-hub-namespace/my-docker-hub-repository- name: Build and push Docker imageuses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671with:context: .file: ./Dockerfilepush: truetags: ${{ steps.meta.outputs.tags }}labels: ${{ steps.meta.outputs.labels }}

简单版 workflow

这是我自己写的 workflow 比 GitHub 提供的例子简单一些

name: Docker Image CI
run-name: ${{ github.actor }} is building a imageon: [push]jobs:build:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v3- name: Build the Docker imagerun: docker build . --file ./next-antd/AIHub.Blazor/Dockerfile --tag ${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}- name: Login to aliyun docker repositoryrun: docker login -u ${{ secrets.ALIYUN_USERNAME }} -p ${{ secrets.ALIYUN_PWD }} ${{ secrets.ALIYUN_DOCKER_REPO }}- name: Push image to aliyun docker repositoryrun: docker push ${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}

这个 build 步骤,在 GitHub 托管的 runner 上构建 docker 镜像,并且推送到私有镜像仓库。

镜像的 tag 版本,我使用了 run_id 这个环境变量,代表本次构建任务的唯一ID,例如 1658821493

也可以使用 ${{ github.sha }} 代表这次的 commit sha ,但我觉得太长了就没有使用

GITHUB_SHA: 触发工作流的提交 SHA。 此提交 SHA 的值取决于触发工作流程的事件。 有关详细信息,请参阅“触发工作流的事件”。 例如,ffac537e6cbbf934b08745a378932722df287a53

PS:官方提供的例子使用的是 $(date +%s) 时间戳,但我还没探索出在环境变量里拼接字符串的方法。

搭建本地 runner

镜像构建完事了,还得在本地的服务器上跑。

很简单,就是把镜像 pull 下来,然后 docker compose up 就行,现在我们把这一步也加入到 workflow 里。

添加 runner

访问这个页面: https://github.com/star-plan/aihub/settings/actions/runners

点击 New self-hosted runner 按钮

选择对应的系统和架构,然后根据里面的命令来就完事了。

本文选择的是 Linux - x64 的方案

GitHub 提供的命令是这样(这里只是给出例子,实际要以自己的项目配置页面为准)

# Create a folder
$ mkdir actions-runner && cd actions-runner# Download the latest runner package
$ curl -o actions-runner-linux-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz# Optional: Validate the hash

其中下载这一步可能会遇到问题,因为某些莫名其妙的原因,GitHub 访问不了,这时候需要使用 proxychains 工具,请自行搜索 + 配置。

PS:好家伙,这个 runner 居然有 180M

接着运行命令 runner

./config.sh --url [REPO_URL] --token [TOKEN]

  • 提示输入 runner group 名称,默认即可

  • 提示需要输入 runner 名字,我输入了个 aihub

  • 接着还可以输入 label 啥的,根据需求来就行

配置搞定之后就启动 runner

./run.sh

安装服务

用 ./run.sh 启动的 runner 并不稳定,退出登录之后就无了,就算使用 & 或者 Ctrl+Z 切换到后台执行,也不是那么稳定。

GitHub runner 可以作为 Linux 服务运行,使用也很简单。

先关掉正在运行的 runner

ps aux | grep run.sh
# 找到 pid 之后 kill 掉
kill -9 pid

安装服务

sudo ./svc.sh install

启动服务

sudo ./svc.sh start

更多操作请查看第四条参考资料。

查看 runner 列表

在 GitHub 页面上查看当前运行的 runner

地址: https://github.com/star-plan/aihub/settings/actions/runners

可以看到已经有一个叫 aihub 的 runner 了

runner 网络代理

这波我只能说 GitHub 太贴心了!他已经考虑到了不能上 GitHub 的情况,他真的,我哭死😭

可以在环境变量里设置代理,也可以在 .env 文件里配置,这里我还是选 .env 吧。

https_proxy=http://proxy.local:8080
no_proxy=example.com,myserver.local:443


更多关于搭建本地 runner 的文档,可以查看参考资料的第三条。

使用本地 runner 部署服务

老规矩,使用 docker-compose 来编排服务。

先创建个目录,里面存放 docker-compose.yml 和一些持久化的文件。

本例子的路径是: /home/apps/aihub

version: '3.6'services:web:image: ${IMAGE}container_name: aihub-testrestart: alwaysenvironment:- ASPNETCORE_ENVIRONMENT=Production- ASPNETCORE_URLS=http://+:80volumes:- ./aihub.app.db:/app/aihub.app.dbports:- "12002:80"networks:- default- swagnetworks:swag:name: swagexternal: truedefault:name: aihub-test

镜像部分我用了环境变量,因为每次构建的镜像tag都不一样,我要在 workflow 里将 tag 写入 .env 文件。当然也可以写固定 latest 。

.env 文件是这样

IMAGE=registry.cn-hangzhou.aliyuncs.com/deali/aihub-test:6861065827

OK,总算是到了最后一步,继续编辑我们的 workflow ,增加一个 deployment 任务。

name: Docker Image CI
run-name: ${{ github.actor }} is building a imageon: [push]jobs:build:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v3- name: Build the Docker imagerun: docker build . --file ./next-antd/AIHub.Blazor/Dockerfile --tag ${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}- name: Login to aliyun docker repositoryrun: docker login -u ${{ secrets.ALIYUN_USERNAME }} -p ${{ secrets.ALIYUN_PWD }} ${{ secrets.ALIYUN_DOCKER_REPO }}- name: Push image to aliyun docker repositoryrun: docker push ${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}deployment:runs-on: [self-hosted, linux, x64]needs: [build]steps:- name: export environment variantrun: echo 'IMAGE=${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}' > /home/apps/aihub/.env- name: docker compose deployrun: docker compose -f /home/apps/aihub/docker-compose.yml --project-directory /home/apps/aihub up -d

注意:

  • jobs 默认是并行执行的,所以需要在 deployment 任务里加上 needs 配置,等 build 完了再部署

  • 使用 jobs.<job_id>.needs 标识运行此作业之前必须成功完成的所有作业。 它可以是一个字符串,也可以是字符串数组。 如果某个作业失败或跳过,则所有需要它的作业都会被跳过,除非这些作业使用让该作业继续的条件表达式。 如果运行包含一系列相互需要的作业,则故障或跳过将从故障点或跳过点开始,应用于依赖项链中的所有作业。 如果希望某个作业在其依赖的作业未成功时也能运行,请在 jobs.<job_id>.if 中使用 always() 条件表达式。

  • deployment 任务是在本地执行的,所以 runs-on 通过多个 label 选择了本地 runner

  • 执行 docker compose 命令的时候工作目录是在 GitHub Action 工具的 _work 目录里,所以需要指定 --project-directory 参数,或者通过 --env-file 指定 .env 文件位置

查看执行结果

在 GitHub Action 页面可以查看执行结果。

搞定!

参考资料

  • 变量 - GitHub 文档

  • 发布 Docker 映像 - GitHub 文档

  • 关于自托管运行程序 - GitHub 文档

  • 将自托管的运行应用程序配置为服务 - GitHub 文档

  • 将代理服务器与自托管运行程序结合使用 - GitHub 文档

  • 在工作流程中使用作业 - GitHub 文档

  • Ways to set environment variables in Compose | Docker Docs

文章转载自:程序设计实验室

原文链接:https://www.cnblogs.com/deali/p/17833948.html

相关文章:

持续集成指南:GitHubAction 自动构建+部署AspNetCore项目

前言 之前研究了使用 GitHub Action 自动构建和发布 nuget 包&#xff1a;开发现代化的.NetCore控制台程序&#xff1a;(4)使用GithubAction自动构建以及发布nuget包 现在更进一步&#xff0c;使用 GitHub Action 在其提供的 runner 里构建 docker 镜像&#xff0c;之后提交到阿…...

Docker 笔记(三)--容器

Docker 笔记&#xff08;三&#xff09;–容器 记录Docker 安装操作记录&#xff0c;便于查询。 参考 链接: Docker 入门到实战教程(三)镜像和容器链接: docker run中的-itd参数正确使用链接: docker官方文档链接: 阿里云Debian 镜像链接: Debian 全球镜像站链接: Debian/Ub…...

gd32关于IO引脚配置的一些问题

一、gd32f103的PA15问题 1、 #define GPIO_SWJ_NONJTRST_REMAP ((uint32_t)0x00300100U) /*!< full SWJ(JTAG-DP SW-DP),but without NJTRST */ #define GPIO_SWJ_SWDPENABLE_REMAP ((uint32_t)0x00300200U) /*!< JTAG-DP disabled and SW-DP enab…...

QT小记:警告Use multi-arg instead

"Use multi-arg instead" 是一个提示&#xff0c;建议使用 QObject::tr() 函数的多参数版本来处理多个占位符&#xff0c;而不是使用单参数版本。 在 Qt 中&#xff0c;tr() 是用于进行文本翻译&#xff08;国际化&#xff09;的函数。它允许你在应用程序中使用多种…...

皮肤性病科专家谭巍主任提出HPV转阴后饮食七点建议

HPV转阴是每一位感染者都期盼的&#xff0c;因为转阴所以健康&#xff0c;只有转为阴性才意味着不具备传染性&#xff0c;从此也不必再害怕将病毒传染给家人的风险&#xff0c;也不必再担忧持续感染而引发的健康风险。总之&#xff0c;HPV转阴是预示感染者恢复健康与否的主要标…...

快速弄懂C++中的智能指针

智能指针是C中的一个对象&#xff0c;它的行为类似于指针&#xff0c;但它提供了自动的内存管理功能。当智能指针超出作用域时&#xff08;比如说在函数中使用智能指针指向了一个对象&#xff0c;当该函数结束时会自动销毁该对象&#xff09;&#xff0c;它会自动删除其所指向的…...

C#调用C++ dll教程

文章目录 一、创建C dll项目二、C#程序员调用C dll三、C与C#数据类型对应基本数据类型对应表C指针类型与C#类型 在使用C#开发客户端时&#xff0c;有时需要调用C dll&#xff0c;本篇博客来介绍C#程序如何调用C dll。 一、创建C dll项目 首先使用VS2022创建C dll项目&#xf…...

计算机毕设 深度学习 大数据 股票预测系统 - python lstm

文章目录 0 前言1 课题意义1.1 股票预测主流方法 2 什么是LSTM2.1 循环神经网络2.1 LSTM诞生 2 如何用LSTM做股票预测2.1 算法构建流程2.2 部分代码 3 实现效果3.1 数据3.2 预测结果项目运行展示开发环境数据获取 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要…...

97.qt qml-自定义Table之实现ctrl与shift多选

我们之前实现了:93.qt qml-自定义Table优化(新增:水平拖拽/缩放自适应/选择使能/自定义委托)-CSDN博客 实现选择使能的时候,我们只能一行行去点击选中,非常麻烦,所以本章我们实现ctrl多选与shift多选、 所以在Table控件新增两个属性: 1.实现介绍 ctrl多选实现原理:当我…...

运行软件报错mfc140.dll丢失?分享mfc140.dll丢失的解决方法

小伙伴们&#xff0c;你是否也有过这样的经历&#xff1a;每当碰到诸如" mfc140.dll 丢失 "之类的烦人错误时&#xff0c;你是不是会一头雾水&#xff0c;完全不知道从何下手去解决&#xff1f;不要担心&#xff0c;接下来咱就给你提供这样一篇实用教程&#xff0c;教…...

milvus数据库-连接

Milvus 支持 19530 和 9091 两个端口&#xff1a; 端口 19530 用于 gRPC 和 RESTful API。 这是您使用不同 Milvus SDK 或 HTTP 客户端连接到 Milvus 服务器时的默认端口。 端口 9091 用于 Kubernetes 内的指标收集、pprof 分析和运行状况探测。 它用作管理端口。 1.连接到数…...

ios + vue3 Teleport + inset 兼容性问题

目录 1&#xff0c;问题表现2&#xff0c;解决步骤1&#xff0c;teleport 的问题2&#xff0c;inset 的问题3&#xff0c;teleport 的问题之二 1&#xff0c;问题表现 使用 vue3 的 Teleport 实现的 dialog 弹窗&#xff0c;但是在 ios app 中嵌套的 h5 中无法打开。 直接在io…...

计蒜客T1654 数列分段(C语言实现)

【题目描述】对于给定的一个长度为n的正整数数列ai&#xff0c;现要将其分成连续的若干段&#xff0c;并且每段和不超过m&#xff08;可以等于m&#xff09;&#xff0c;问最少能将其分成多少段使得满足要求。 【输入格式】第一行包含两个正整数n&#xff0c;m&#xff0c;表示…...

Linux进程——system函数、popen函数

system函数&#xff08;执行shell 命令&#xff09; 头文件 #include <stdlib.h> 函数定义 int system(const char * string); 函数说明 system()会调用fork()产生子进程&#xff0c;由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令&#xff0c;…...

【智能家居】5、主流程设计以及外设框架编写与测试

目录 一、主流程设计 1、工厂模式结构体定义 &#xff08;1&#xff09;指令工厂 inputCmd.h &#xff08;2&#xff09;外设工厂 controlDevices.h 二、外设框架编写 1、创建外设工厂对象bathroomLight 2、编写相关函数框架 3、将浴室灯相关操作插入外设工厂链表等待被调…...

详解ssh远程登录服务

华子目录 简介概念功能 分类文字接口图形接口 文字接口ssh连接服务器浅浅介绍一下加密技术凯撒加密加密分类对称加密非对称加密非对称加密方法&#xff08;也叫公钥加密&#xff09; ssh两大类认证方式&#xff1a;连接加密技术简介密钥解析 ssh工作过程版本协商阶段密钥和算法…...

LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄

接着前两节的Langchain&#xff0c;继续实现Langchain中的Agent LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字 代码实现 # 从langchain库中导入模块 from langchain.llms import OpenAI # 从langchain.l…...

wpf devexpress绑定grid到总计和分组统计

此主题描述了如何在gridcontrol中的视图模型和显示定义总计和分组统计 在视图模型中指定统计 1、创建 SummaryItemType 枚举你想要在GridControl中显示的统计类型&#xff1a; public enum SummaryItemType { Max, Count, None } 2、创建一个grid统计描述类 public class S…...

嵌入式 Linux 移植与系统启动方法

1、Linux系统启动与U-Boot 所谓移植就是把程序代码从一种运行环境转移到另一种运行环境。对于内核移植来说&#xff0c;主要是从一种硬件平台转移到另一种硬件平台上运行。 体系结构级别的移植是指在不同体系结构平台上Linux内核的移植&#xff0c;例如&#xff0c;在ARM、MI…...

代码随想录算法训练营|五十六天

回文子串 647. 回文子串 - 力扣&#xff08;LeetCode&#xff09; dp含义&#xff1a;表示区间内[i,j]是否有回文子串&#xff0c;有true&#xff0c;没有false。 递推公式&#xff1a;当s[i]和s[j]不相等&#xff0c;false&#xff1b;相等时&#xff0c;情况一&#xff0c;…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...