社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Git

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

dotNET跨平台 • 6 月前 • 124 次点击  

1前言

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

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

本文以 AIHub 项目为例。

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

2准备 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 .

一切正常可以进入下一步

3创建私有镜像仓库

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

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

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

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

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

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

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

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

4 配置 GitHub Action Secret

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

这里我设置的名字是

  • ALIYUN_DOCKER_REPO
  • ALIYUN_USERNAME
  • ALIYUN_PWD

5构建镜像

编写 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) 时间戳,但我还没探索出在环境变量里拼接字符串的方法。

6搭建本地 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 的文档,可以查看参考资料的第三条。

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

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

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

8查看执行结果

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

搞定!

9参考资料

  • https://docs.github.com/zh/actions/learn-github-actions/variables
  • https://docs.github.com/zh/actions/publishing-packages/publishing-docker-images
  • https://docs.github.com/zh/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners
  • https://docs.github.com/zh/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service
  • https://docs.github.com/zh/actions/hosting-your-own-runners/managing-self-hosted-runners/using-a-proxy-server-with-self-hosted-runners
  • https://docs.github.com/zh/actions/using-jobs/using-jobs-in-a-workflow
  • https://docs.docker.com/compose/environment-variables/set-environment-variables/


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/164437
 
124 次点击