系列导航及源代码

需求和目标

在这个系列的最后一节中,我们将使用GitHub Actions将TodoList应用部署到Azure Container Instance上。

实现

为了确保部署的应用能够正确运行,我们需要做以下几件事:

创建Azure SQL Server实例

选择最便宜的数据库规格就可以了,新建一个ResourceGroup名为todolist,并新建数据库实例,获得连接字符串:

创建Azure Container Registry

用于构建好的镜像上传和部署

设置GitHub Secrets

首先创建Service Principle认证:

groupId=$(az group show \
--name todolist \
--query id --output tsv) az ad sp create-for-rbac \
--scope $groupId \
--role Contributor \
--sdk-auth # 会得到类似下面的输出
{
"clientId": "xxxx6ddc-xxxx-xxxx-xxx-ef78a99dxxxx",
"clientSecret": "xxxx79dc-xxxx-xxxx-xxxx-aaaaaec5xxxx",
"subscriptionId": "xxxx251c-xxxx-xxxx-xxxx-bf99a306xxxx",
"tenantId": "xxxx88bf-xxxx-xxxx-xxxx-2d7cd011xxxx",
"activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
"resourceManagerEndpointUrl": "https://management.azure.com/",
"activeDirectoryGraphResourceId": "https://graph.windows.net/",
"sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
"galleryEndpointUrl": "https://gallery.azure.com/",
"managementEndpointUrl": "https://management.core.windows.net/"
}

接下来更新Registry的认证

registryId=$(az acr show \
--name code4nothing \
--query id --output tsv) az role assignment create \
--assignee <ClientId> \
--scope $registryId \
--role AcrPush

最后将Secrets配置到Github Repo的设置里:

具体的参数说明请参考:Save credentials to GitHub repo

创建Actions配置

在Github的Repo里选择Actions,选择set up a workflow yourself

定义以下构建步骤:

on: [push]
name: Linux_Container_Workflow jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
# checkout the repo
- name: 'Checkout GitHub Action'
uses: actions/checkout@main - name: 'Login via Azure CLI'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }} - name: 'Build and push image'
uses: azure/docker-login@v1
with:
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- run: |
docker build -f src/TodoList.Api/Dockerfile.prod . -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/todolist:${{ github.sha }}
docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/todolist:${{ github.sha }}
- name: 'Deploy to Azure Container Instances'
uses: 'azure/aci-deploy@v1'
with:
resource-group: ${{ secrets.RESOURCE_GROUP }}
dns-name-label: ${{ secrets.RESOURCE_GROUP }}${{ github.run_number }}
image: ${{ secrets.REGISTRY_LOGIN_SERVER }}/todolist:${{ github.sha }}
registry-login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
registry-username: ${{ secrets.REGISTRY_USERNAME }}
registry-password: ${{ secrets.REGISTRY_PASSWORD }}
name: aci-todolist
location: 'east asia'

修改项目代码以进行Production部署

  • Dockerfile.prod
ARG NET_IMAGE=6.0-bullseye-slim
FROM mcr.microsoft.com/dotnet/aspnet:${NET_IMAGE} AS base
WORKDIR /app
EXPOSE 80
ENV ASPNETCORE_ENVIRONMENT=Production FROM mcr.microsoft.com/dotnet/sdk:${NET_IMAGE} AS build
WORKDIR /src
COPY ["src/TodoList.Api/TodoList.Api.csproj", "TodoList.Api/"]
COPY ["src/TodoList.Application/TodoList.Application.csproj", "TodoList.Application/"]
COPY ["src/TodoList.Domain/TodoList.Domain.csproj", "TodoList.Domain/"]
COPY ["src/TodoList.Infrastructure/TodoList.Infrastructure.csproj", "TodoList.Infrastructure/"]
RUN dotnet restore "TodoList.Api/TodoList.Api.csproj"
COPY ./src .
WORKDIR "/src/TodoList.Api"
RUN dotnet build "TodoList.Api.csproj" -c Release -o /app/build FROM build AS publish
RUN dotnet publish --no-restore "TodoList.Api.csproj" -c Release -o /app/publish FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "TodoList.Api.dll"]
  • appsettings.Production.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"UseFileToLog": true,
"ConnectionStrings": {
"SqlServerConnection": "Server=tcp:code4nothing.database.windows.net,1433;Initial Catalog=TodoListDb;Persist Security Info=False;User ID=code4nothing;Password=TestTodo@123;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
}
}

将代码合并到main上以后,自动触发Actions:

ACI实例运行起来后可以看到:

验证

我们从本地的Insomia上访问API端口,先看看liveness probes是否正常工作:

请求的host可以从这里获取:

查询TodoList后查询TodoItems结果:

一点扩展

微软新推出的Azure服务Azure Container Apps(preview)是作为容器化服务部署的另一个选择,简单的说明:

Deploy containerized apps without managing complex infrastructure. Write code using your preferred programming language or framework, and build microservices with full support for Distributed Application Runtime (Dapr). Scale dynamically based on HTTP traffic or events powered by Kubernetes Event-Driven Autoscaling (KEDA).

来自官方文档Azure Container Apps

总结

如果在部署ACI的过程中失败了,尤其是容器在ACI中没有成功运行,可以参考:Troubleshoot common issues in Azure Container Instances来查看和解决问题。

在本文中我们实现了如何将应用通过Github Actions部署到Azure Container Instance服务中。那么到本节为止,使用.NET 6开发TodoList应用文章索引这个用于串联.NET Web API开发基础系列的文章就结束了,感谢各位朋友在此过程中的支持。

在这个系列的写作和发表中,我们还漏掉了几篇文章暂时没有完成,包括有评论指出的几个没有填完的坑,我会找时间尽量都补齐。但是更新速度应该不会像写这个系列的时候那么密集了。

后面的计划是,在正式开始微服务系列实践文章开始之前,会写几个小的系列来预先熟悉一下后面也许会用到的知识点,例如GraphQL,RabbitMQ,gRPC,Envoy以及Dapr等内容。

感谢各位对文章中错误的指正,希望我们能继续一起努力,一步一个脚印地掌握更多的技能。

参考资料

  1. Configure a GitHub action to create a container instance
  2. Troubleshoot common issues in Azure Container Instances
  3. Azure Container Apps

使用.NET 6开发TodoList应用(31)——实现基于Github Actions和ACI的CI/CD的更多相关文章

  1. 使用.NET 6开发TodoList应用(24)——实现基于JWT的Identity功能

    系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 在.NET Web API开发中还有一个很重要的需求是关于身份认证和授权的,这个主题非常大,所以本文不打算面面俱到地介绍整个主 ...

  2. 使用.NET 6开发TodoList应用(3)——引入第三方日志库

    需求 在我们项目开发的过程中,使用.NET 6自带的日志系统有时是不能满足实际需求的,比如有的时候我们需要将日志输出到第三方平台上,最典型的应用就是在各种云平台上,为了集中管理日志和查询日志,通常会选 ...

  3. 使用.NET 6开发TodoList应用(1)——系列背景

    前言 想到要写这样一个系列博客,初衷有两个:一是希望通过一个实践项目,将.NET 6 WebAPI开发的基础知识串联起来,帮助那些想要入门.NET 6服务端开发的朋友们快速上手,对使用.NET 6开发 ...

  4. 使用.NET 6开发TodoList应用(2)——项目结构搭建

    为了不影响阅读的体验,我把系列导航放到文章最后了,有需要的小伙伴可以直接通过导航跳转到对应的文章 : P TodoList需求简介 首先明确一下我们即将开发的这个TodoList应用都需要完成什么功能 ...

  5. 使用.NET 6开发TodoList应用(4)——引入数据存储

    需求 作为后端CRUD程序员(bushi,数据存储是开发后端服务一个非常重要的组件.对我们的TodoList项目来说,自然也需要配置数据存储.目前的需求很简单: 需要能持久化TodoList对象并对其 ...

  6. 使用.NET 6开发TodoList应用(5)——领域实体创建

    需求 上一篇文章中我们完成了数据存储服务的接入,从这一篇开始将正式进入业务逻辑部分的开发. 首先要定义和解决的问题是,根据TodoList项目的需求,我们应该设计怎样的数据实体,如何去进行操作? 长文 ...

  7. 使用.NET 6开发TodoList应用(5.1)——实现Repository模式

    需求 经常写CRUD程序的小伙伴们可能都经历过定义很多Repository接口,分别做对应的实现,依赖注入并使用的场景.有的时候会发现,很多分散的XXXXRepository的逻辑都是基本一致的,于是 ...

  8. 使用.NET 6开发TodoList应用(6)——使用MediatR实现POST请求

    需求 需求很简单:如何创建新的TodoList和TodoItem并持久化. 初学者按照教程去实现的话,应该分成以下几步:创建Controller并实现POST方法:实用传入的请求参数new一个数据库实 ...

  9. 使用.NET 6开发TodoList应用文章索引

    系列导航 使用.NET 6开发TodoList应用(1)--系列背景 使用.NET 6开发TodoList应用(2)--项目结构搭建 使用.NET 6开发TodoList应用(3)--引入第三方日志 ...

随机推荐

  1. [BUUCTF]PWN——ciscn_2019_ne_5

    ciscn_2019_ne_5 题目附件 步骤: 例行检查,32位,开启了nx保护 试运行一下程序,看一下程序的大概执行情况 32位ida载入,shift+f12查看程序里的字符串,发现了flag字符 ...

  2. 录入任务信息(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 日历设置好了,就该录入任务了.当然在录入任务之前还要对任务进行一下面分解,就是一个项目,要分几个大步完成,每个大步又分几个 ...

  3. LuoguP6553 Strings of Monody 题解

    Content 给定一个长度为 \(n\) 的字符串 \(s\)(仅包含 \(1,4,5\) 三种字符,\(n\) 在本题中无需输入),有 \(m\) 个操作,每次操作给定两个整数 \(l,r\),再 ...

  4. CF513B1 Permutations 题解

    Content 给定两个整数 \(n,m\).定义 \(f(p)=\sum\limits_{l=1}^n\sum\limits_{r=l}^n\min\limits_{i=l}^rp_i\),其中 \ ...

  5. java 输入输出IO 转换流-字符编码

    编码和其产生的问题: 计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字.英文.标点符号.汉字等字符是二进制数转换之后的结果. 按照某种规则,将字符存储到计算机中,称为编码 .反之,将存 ...

  6. ORACLE数据库登录显示ORA-28001: the password has expired

    Oracle数据库登录显示 "这个密码已过期,请输入新密码" 点击win键 找到Oracle的SQL Plus 点击打开之后输入登录的用户名密码,然后会显示该密码已过期,输入新口令 ...

  7. 【LeetCode】404. Sum of Left Leaves 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目大意 题目大意 解题方法 递归 迭代 日期 [LeetCode] 题目地址:h ...

  8. 【LeetCode】Swap Nodes in Pairs 解题报告

    Swap Nodes in Pairs [LeetCode] https://leetcode.com/problems/swap-nodes-in-pairs/ Total Accepted: 95 ...

  9. 【LeetCode】581. Shortest Unsorted Continuous Subarray 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 解题方法 方法一:排序比较 日期 题目地址:https://leetco ...

  10. 【LeetCode】721. Accounts Merge 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/accounts ...