打开/关闭搜索
搜索
打开/关闭菜单
66
947
83
2889
md5.pw
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
上传文件
打开/关闭外观设置菜单
通知
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
登录
请求账号
查看“︁实战笔记:搬瓦工 Docker 部署 .NET 8 与 BWH API 自动监控流水线”︁的源代码
来自md5.pw
分享此页面
更多语言
查看
阅读
查看源代码
查看历史
associated-pages
页面
讨论
更多操作
←
实战笔记:搬瓦工 Docker 部署 .NET 8 与 BWH API 自动监控流水线
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
最近社区里有不少帖子在讨论各种面板、测速,或者教大家写 Bash 脚本查 VPS 流量。 其实对于开发者来说,买一台网络稳的机器(比如搬瓦工的 GIA),最大的用途还是跑自己的后端服务。但这年头,如果每次改完代码还要手动 FTP 传文件、在宿主机折腾各种运行时环境,不仅容易把系统弄脏,维护起来也挺繁琐。 今天分享一套我日常在用的 DevOps 工作流:在 Linux 下用 '''Docker Compose''' 隔离运行 .NET 8 服务,搭配 '''GitHub Actions''' 做全自动 CI/CD。顺便用 C# 对接一下搬瓦工官方的 KiwiVM API,写个 Telegram 监控端。废话不多说,直接开始。 == 01. 代码实现:C# 调用 KiwiVM API 与 TG 机器人 == 相比传统的 Bash 脚本定时任务,用 C# 的 <code>BackgroundService</code> 做长连接监控更稳定。另外,很多人用脚本查 API 经常会算错流量,主要是没留意官方文档里的两个细节:'''搬瓦工的高端机房流量是有 <code>monthly_data_multiplier</code>(流量乘数)的,而且 API 返回的日期是 UNIX 时间戳。''' 我们在 .NET 8 Worker 项目中引入 <code>Telegram.Bot</code>,顺手把这两个容易踩坑的地方处理掉: <syntaxhighlight lang="csharp"> using Telegram.Bot; using Telegram.Bot.Types; using System.Net.Http.Json; public class BwhMonitorWorker : BackgroundService { private readonly TelegramBotClient _botClient = new("你的_TG_BOT_TOKEN"); private readonly HttpClient _http = new(); private const string API_HOST = "https://" + "api.64clouds.com"; private const string VEID = "你的VEID"; private const string API_KEY = "你的API_KEY"; private const long ADMIN_CHAT_ID = 123456789; // 你的 TG 账号 ID protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _botClient.StartReceiving(HandleUpdateAsync, HandleErrorAsync, null, stoppingToken); while (!stoppingToken.IsCancellationRequested) await Task.Delay(1000, stoppingToken); } private async Task HandleUpdateAsync(ITelegramBotClient bot, Update update, CancellationToken ct) { if (update.Message?.Text == null || update.Message.Chat.Id != ADMIN_CHAT_ID) return; var text = update.Message.Text; var chatId = update.Message.Chat.Id; if (text == "/status") { var url = $"{API_HOST}/v1/getServiceInfo?veid={VEID}&api_key={API_KEY}"; var res = await _http.GetFromJsonAsync<BwhInfo>(url, ct); if (res.error == 0) { // 细节 1:计算时必须带上官方规定的流量乘数 (monthly_data_multiplier) double multiplier = res.monthly_data_multiplier > 0 ? res.monthly_data_multiplier : 1; double usedGb = (res.data_counter * multiplier) / 1024.0 / 1024.0 / 1024.0; double limitGb = (res.plan_monthly_data * multiplier) / 1024.0 / 1024.0 / 1024.0; // 细节 2:UNIX 时间戳转换为本地直观时间 DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(res.data_next_reset).LocalDateTime; await bot.SendTextMessageAsync(chatId, $"🖥️ 主机名: {res.hostname}\n" + $"📍 节点: {res.node_location}\n" + $"📶 流量: {usedGb:F2}GB / {limitGb:F2}GB\n" + $"📅 重置: {resetDate:yyyy-MM-dd HH:mm:ss}", cancellationToken: ct); } } else if (text == "/reboot") { var url = $"{API_HOST}/v1/restart?veid={VEID}&api_key={API_KEY}"; var res = await _http.GetFromJsonAsync<BwhInfo>(url, ct); if(res.error == 0) { await bot.SendTextMessageAsync(chatId, "🔄 硬件重启指令已发送,请稍候...", cancellationToken: ct); } } } private Task HandleErrorAsync(ITelegramBotClient bot, Exception ex, CancellationToken ct) => Task.CompletedTask; } // 对应官方文档的 JSON 映射类 public class BwhInfo { public int error { get; set; } public string hostname { get; set; } public string node_location { get; set; } public long data_counter { get; set; } public long plan_monthly_data { get; set; } public double monthly_data_multiplier { get; set; } public long data_next_reset { get; set; } } </syntaxhighlight> == 02. Docker 容器化:告别环境污染 == 我们不需要在宿主机上装任何 .NET SDK 或运行时,直接把程序打包进 Docker。这样不仅系统干净,而且自带进程守护(挂了自动拉起),省去了配置 Systemd 的麻烦。 在代码根目录下新建这两个文件: '''1. <code>Dockerfile</code>'''(极简运行时镜像): <syntaxhighlight lang="docker"> # 使用微软官方轻量级 ASP.NET 8 运行时镜像 FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /app # 拷贝编译好的文件到容器内 COPY . . # 启动程序 (替换为你的 DLL 名字) ENTRYPOINT ["dotnet", "MyBwhBot.dll"] </syntaxhighlight> '''2. <code>docker-compose.yml</code>''': <syntaxhighlight lang="yaml"> services: bwh-bot: build: . container_name: bwh-telegram-bot restart: always # 容器挂了自动重启 environment: - TZ=Asia/Shanghai </syntaxhighlight> == 03. GitHub Actions 全自动化 CI/CD == 服务和容器配置都准备好了,接下来的痛点是怎么自动化部署。这里我们直接用 GitHub Actions 搞定。 只要你往 <code>main</code> 分支推代码,GitHub 就会自动走完这个流程:装 .NET SDK -> 编译代码 -> 打包连同 Docker 文件一起 SCP 传到服务器 -> 最后通过 SSH 触发 <code>docker compose up</code> 构建并重启。 在代码仓库新建 <code>.github/workflows/deploy.yml</code> 文件: <syntaxhighlight lang="yaml"> name: Docker Deploy to BWH on: push: branches: [ "main" ] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 配置 .NET 8 编译环境 uses: actions/setup-dotnet@v4 with: dotnet-version: '8.0.x' - name: 编译发布 run: dotnet publish -c Release -o ./publish_out - name: 准备 Docker 文件 run: | cp Dockerfile ./publish_out/ cp docker-compose.yml ./publish_out/ - name: SCP 传输文件到服务器 uses: appleboy/scp-action@v0.1.7 with: host: ${{ secrets.BWH_IP }} # 你的 VPS IP username: root key: ${{ secrets.SSH_PRIVATE_KEY }} # 私钥 (在 GitHub 后台配置) source: "./publish_out/*" target: "/opt/bwh-bot" strip_components: 1 - name: SSH 触发 Docker 重新构建 uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.BWH_IP }} username: root key: ${{ secrets.SSH_PRIVATE_KEY }} script: | cd /opt/bwh-bot docker compose down docker compose up -d --build docker image prune -f # 清理旧的无用镜像 </syntaxhighlight> <blockquote>'''提示''':记得在 GitHub 仓库的 <code>Settings -> Secrets and variables -> Actions</code> 里把 <code>BWH_IP</code> 和 <code>SSH_PRIVATE_KEY</code> 填好。</blockquote> == 总结 == 配置好之后,以后每次在本地更新完代码只要 push 一下,云端的服务就会自动完成重建和替换。 这套流程其实对 VPS 的网络连通性有一定要求。如果服务器网络比较差,GitHub Action 在 SCP 传文件或者 SSH 连接时偶尔会超时报错。平时部署后端服务,建议尽量选网络稳一点的机房(类似 搬瓦工 CN2 GIA 高端线这种),文件传输基本秒达,CI/CD 流水线跑起来会顺畅很多。 [[Category:500 常见应用指南 — Application Guides]]
返回
实战笔记:搬瓦工 Docker 部署 .NET 8 与 BWH API 自动监控流水线
。
查看“︁实战笔记:搬瓦工 Docker 部署 .NET 8 与 BWH API 自动监控流水线”︁的源代码
来自md5.pw