Linux amd64 WebAPI + 多 ClientApp 的 Drone 示例
本页基于一个真实 Linux pipeline 的结构进行脱敏拆解,重点帮助读者理解:同一仓库里有 WebAPI、多个前端应用、统一发布目录、Docker 镜像和 Kubernetes 部署时,Drone 步骤应该如何分层。页面保留原路径,方便历史链接继续使用。
正式规范请先看 Drone CI 配置专题;Windows / Mac 示例请看 Windows / Mac Runner 的 Drone 示例。
这份示例适合看什么
type: exec的 Linux runner 如何承接 Docker、Kubernetes 和共享缓存目录。- 多个前端应用如何并行构建,再统一同步到后端发布目录。
dotnet publish、镜像打包和kubectl set image如何串成一条交付链。- Docker 发布的 ASP.NET WebAPI / Web 宿主项目,怎样把运行时版本号一起带进镜像。
- 哪些字段是结构性做法,哪些字段只是项目示例值,必须替换。
流水线总览
- pipeline 类型:
exec - pipeline 名称:
build-pipeline - runner 节点:
cn-build-02 - 平台:
linux / amd64 - 触发条件:
push到指定分支
这条流水线先准备 Docker 和 Kubernetes 运行环境,再并行构建多个前端应用与后端发布目录,随后把前端产物同步到后端发布目录,最后构建并推送镜像,再执行滚动更新。
脱敏后的结构示例
---
kind: pipeline
name: build-pipeline
type: exec
platform:
os: linux
arch: amd64
node:
runner_name: cn-build-02
trigger:
branch:
- main
event:
- push
steps:
- name: docker-config
commands:
- bash scripts/ci/linux-prepare.sh
- name: build-portal
depends_on:
- docker-config
commands:
- bash scripts/ci/build-portal.sh
- name: build-admin
depends_on:
- docker-config
commands:
- bash scripts/ci/build-admin.sh
- name: publish-backend
depends_on:
- docker-config
commands:
- bash scripts/ci/publish-backend.sh
- name: sync-clientapp
depends_on:
- build-portal
- build-admin
- publish-backend
commands:
- bash scripts/ci/sync-clientapp.sh
- name: package-image
depends_on:
- sync-clientapp
commands:
- bash scripts/ci/package-image.sh
- name: deploy
depends_on:
- package-image
commands:
- bash scripts/ci/deploy.sh
这个版本刻意把真实仓库地址、镜像名、命名空间、deployment 名称和长命令收敛到脚本中,方便读者先理解结构。
步骤拆解
docker-config
这一层通常负责:
- 准备
~/.docker或 runner 上的 Docker 登录态 - 准备
~/.kube或部署脚本需要的集群上下文 - 验证
docker login、kubectl get nodes等基础可用性 - 检查共享缓存目录是否存在
它本质上是 runner 环境预热。后续大多数步骤都依赖它,因为一旦 Docker 或 Kubernetes 凭据有问题,越早失败越容易定位。
前端构建步骤
典型前端步骤包括:
build portal assetsbuild chatwebbuild dashboardwebbuild adminwebbuild statuswebbuild toolsweb
这些步骤通常都依赖 docker-config,并统一通过某个 Node 构建镜像执行:
- 把当前仓库挂载到工作目录
- 把共享
pnpm store挂载到固定缓存目录 - 在各自应用目录执行
pnpm install - 继续执行
test、typecheck、build
可复用的思路:
- Node 构建镜像版本统一,减少不同前端应用之间的环境漂移。
pnpm store用共享目录缓存,减少重复下载。- 前端步骤只生成
dist,不直接写最终发布目录。
publish-backend
这一层只做后端发布:
- 执行
dotnet publish - 输出到固定发布目录
- 生成一次构建版本号
- 将版本号写入发布目录中的
version.txt,供后续步骤复用
推荐原因:
- 把“后端发布”和“镜像构建”拆开,更容易单独排查
dotnet publish失败。 - 版本号写到发布目录后,镜像构建与部署都可以消费同一份结果。
- 运行中的应用可以通过
AppContext.BaseDirectory/version.txt读取当前发布版本,再由/fwdiag/v暴露出来。
一个脱敏后的最小示意可以是:
dotnet publish src/Your.WebHost/Your.WebHost.csproj -c Release -o ./artifacts/publish
echo "$BUILD_VERSION" > ./artifacts/publish/version.txt
sync-clientapp
这是整个 Linux 多应用示例里最关键的汇总步骤:
- 等待后端发布完成
- 等待所有前端构建完成
- 把各前端产物同步到最终发布目录中的
ClientApp/... - 不再承担编译职责,只做产物收敛
如果你的项目托管多个前端入口,这一步强烈建议放到脚本里,例如 scripts/frontend/sync-all-apps-to-publish.sh。这样后续新增一个前端入口时,只需要调整脚本或映射表,不需要在 YAML 里复制很多段 cp 或 rsync。
package-image
这一层负责:
- 从发布目录读取版本号
- 基于最终发布目录构建镜像
- 推送镜像到仓库
关键点是:镜像步骤应该只消费最终发布目录,而不是回头重新跑一遍 dotnet publish 或前端构建。对于 Docker 发布项目来说,version.txt 也必须跟随最终发布目录一起进入镜像,否则镜像 tag 虽然带了版本,应用运行时仍然无法通过 /fwdiag/v 读取当前发布版本。
脱敏示意:
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY artifacts/publish/ ./
ENTRYPOINT ["dotnet", "Your.WebHost.dll"]
在这种写法里,只要 artifacts/publish/version.txt 已经存在,容器启动后的 AppContext.BaseDirectory/version.txt 就会是同一份文件。
deploy
这一层负责:
- 基于上一步生成的镜像标签执行部署
- 使用
kubectl set image或项目自己的部署脚本完成滚动更新
部署步骤与构建步骤要共享同一套版本来源,避免“打出来的是 A,部署出去的是 B”。
依赖链说明
docker-config是大多数步骤的共同前置。- 多个前端应用在
docker-config完成后并行构建。 publish-backend可以与部分前端构建并行,只要它依赖的前置已经满足。sync-clientapp是完整汇总点,等待所有必要构建完成。package-image与deploy只消费汇总好的最终产物。- 版本文件、镜像 tag 和部署动作都应共享同一份版本来源。
这种组织方式的优点是:
- 并行度高
- 问题边界清晰
- 产物流向稳定
- 后续增加前端应用时不需要重写整条流水线
哪些字段必须替换
下面这些值即使在真实项目中存在,也只能当示例值看,迁移到别的项目时必须替换:
- 镜像仓库地址
- 镜像命名空间
- 镜像名称
- Kubernetes namespace
- deployment 名称
kubectl资源名- 共享缓存目录路径
- 具体 Node / .NET 构建镜像名
- 仓库内部的项目路径
runner_name: cn-build-02 是否替换,要看它是不是你们团队约定的 Linux runner。如果这正是团队固定 runner,可以保留;如果不是,就必须改成目标环境的 runner 名称。
这份示例最值得复用的点
- 用单独步骤准备 Docker、Kubernetes 和认证上下文。
- 用共享目录缓存
pnpm、NuGet 和 .NET SDK。 - 将前端构建拆成独立步骤并行执行。
- 用脚本统一同步前端产物到后端发布目录。
- 在发布目录里写入
version.txt,并让它随最终发布目录一起进入镜像。 - 让版本文件、镜像标签、部署版本统一来源,避免“镜像版本”和“应用自报版本”不一致。