前言

之前研究了使用 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 443 FROM 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/build FROM build AS publish
RUN dotnet publish "AIHub.Blazor.csproj" -c Release -o /app/publish /p:UseAppHost=false FROM 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 image on:
release:
types: [published] jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v4 - name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} - name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: my-docker-hub-namespace/my-docker-hub-repository - name: Build and push Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

简单版 workflow

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

name: Docker Image CI
run-name: ${{ github.actor }} is building a image on: [push] jobs: build: runs-on: ubuntu-latest steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build . --file ./next-antd/AIHub.Blazor/Dockerfile --tag ${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}
- name: Login to aliyun docker repository
run: docker login -u ${{ secrets.ALIYUN_USERNAME }} -p ${{ secrets.ALIYUN_PWD }} ${{ secrets.ALIYUN_DOCKER_REPO }}
- name: Push image to aliyun docker repository
run: 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-test
restart: always
environment:
- ASPNETCORE_ENVIRONMENT=Production
- ASPNETCORE_URLS=http://+:80
volumes:
- ./aihub.app.db:/app/aihub.app.db
ports:
- "12002:80"
networks:
- default
- swag networks:
swag:
name: swag
external: true
default:
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 image on: [push] jobs: build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker build . --file ./next-antd/AIHub.Blazor/Dockerfile --tag ${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}
- name: Login to aliyun docker repository
run: docker login -u ${{ secrets.ALIYUN_USERNAME }} -p ${{ secrets.ALIYUN_PWD }} ${{ secrets.ALIYUN_DOCKER_REPO }}
- name: Push image to aliyun docker repository
run: docker push ${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }} deployment:
runs-on: [self-hosted, linux, x64]
needs: [build]
steps:
- name: export environment variant
run: echo 'IMAGE=${{ secrets.ALIYUN_DOCKER_REPO }}:${{ github.run_id }}' > /home/apps/aihub/.env
- name: docker compose deploy
run: 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 页面可以查看执行结果。

搞定!

参考资料

持续集成指南:GitHubAction 自动构建+部署AspNetCore项目的更多相关文章

  1. Ant + Jenkies +Tomcat 自动构建部署Web项目

    前言:博主资历尚浅,很多东西都还在刚起步学习的阶段,这几天开发任务比较轻,就在自己window系统下,模拟部署远程服务器,利用Jenkies + Ant + Tomcat 搭建了一个自动发布部署的环境 ...

  2. 使用GithubAction自动构建部署项目

    目录 1.1 项目准备 2.1 GithubAction设置 3.1 运行测试 4.1 小结 GitHub Actions 是一种持续集成和持续交付(CI/CD) 平台,可用于自动执行生成.测试和部署 ...

  3. 用持续集成工具Travis进行构建和部署

    用持续集成工具Travis进行构建和部署 用持续集成工具Travis进行构建和部署 摘要:本文简单说明了如何使用持续集成工具Travis进行构建和部署的过程. 1. 概述 持续集成(Continuou ...

  4. Jenkins持续集成(下)-Jenkins部署Asp.Net网站自动发布

    环境:Windows 2008 R2.Jenkins2.235.1.Visual Studio 2017: 概要 前面写过一篇文章,<自动发布-asp.net自动发布.IIS站点自动发布(集成S ...

  5. 使用Docker+Jenkins自动构建部署

    环境 Windows 10 Docker Version 18.06.1-ce-win73 (19507) 运行jenkins 运行jenkins 容器 docker run -d --name ln ...

  6. 使用Visual Studio Team Services持续集成(一)——构建ASP.NET Core

    使用Visual Studio Team Services持续集成(一)--构建ASP.NET Core 概述 持续集成(CI)是将代码尽可能频繁地集成到共享仓库中的过程.在代码集成期间,构建中断或测 ...

  7. 使用jenkins进行项目的自动构建部署

    jenkins 简介 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括:持续的软件版本发布/测试项目和监控外部调用执行的工作. 官网地址地址: https://je ...

  8. 实现自动构建编译javaweb项目并发布到N台服务器

    前言 当你使用nginx实现了负载均衡,当你有了超过3台以上的应用服务器时,一个特别头疼的问题就来了,发布项目好麻烦. 你每次都要在本地编译打包一遍,然后手动复制到每一台服务器上面去,如果只有一两台服 ...

  9. spring-boot-plusV1.2.3发布,CentOS快速安装环境/构建/部署/启动项目

    spring-boot-plusV1.2.3发布,CentOS快速安装环境/构建/部署/启动项目 [V1.2.3-RELEASE] 2019.09.09

  10. 使用Docker搭建Jenkins+Docker持续集成环境(自动化构建发布部署)

    本文介绍如何通过Jenkins的docker镜像从零开始构建一个基于docker镜像的持续集成环境,包含自动化构建.发布到仓库\并部署上线. 0. 前置条件 服务器安装docker,并启动docker ...

随机推荐

  1. 通过Proxy和Reflect实现vue的响应式原理

    vue3通过Proxy+Reflect实现响应式,vue2通过defineProperty来实现 Proxy Proxy是什么 Proxy是ES6中增加的类,表示代理. 如果我们想要监听对象的操作过程 ...

  2. [kvm]cpu内存硬盘配置

    修改CPU配置 如果配置了最大CPU # 临时 virsh setvcpus test 2 # 永久 virsh setvcpus test 2 --config 热增加虚拟机的CPU数后,使用lsc ...

  3. 【opencv】传统目标检测:Haar检测器实现人脸检测

    传统目标分类器主要包括Viola Jones Detector.HOG Detector.DPM Detector,本文主要介绍VJ检测器,在VJ检测器基础上发展出了Haar检测器,Haar检测器也是 ...

  4. 【路由器】Breed 介绍、刷入和使用

    目录 介绍 文件说明 刷入 Breed 通过 Breed 刷机 其他功能 参考资料 介绍 Breed 是国内个人 hackpascal 开发的闭源 Bootloader,也被称为"不死鸟&q ...

  5. 解放双手!ChatGPT助力编写JAVA框架

    亲爱的Javaer们,在平时编码的过程中,你是否曾想过编写一个Java框架去为开发提效?但是要么编写框架时感觉无从下手,不知道从哪开始.要么有思路了后对某个功能实现的技术细节不了解,空有想法而无法实现 ...

  6. 使用API接口获取商品数据

    ​ 在当今的数字化时代,商品数据的获取对于各种规模的企业来说都至关重要.这些数据可以帮助企业进行市场分析,制定销售策略,优化库存管理,以及实现精准营销.API(应用程序编程接口)是一种便捷的方式来获取 ...

  7. Elasticsearch之索引简单应用

    本篇所有操作都在 Kibana 上执行 创建第一个索引 PUT product { // 索引设置 "settings": { // 分片数量 "number_of_sh ...

  8. .NET周刊【9月第1期 2023-09-03】

    国内文章 如何正确实现一个自定义 Exception https://www.cnblogs.com/kklldog/p/how-to-design-exception.html 最近在公司的项目中, ...

  9. List取指定元素

    例如: List<string> list = new List<string>(); list.Take(50).ToList();//取前50条 list.Skip(10) ...

  10. 小知识:调整OCI实例的时区

    之前在随笔中<Linux (RHEL)修改时区> 介绍了时区修改方法. 默认OCI实例中,时区是GMT,在国内用看着这个时区就是很别扭的事情,于是修改时区,实测无需配置 /etc/sysc ...